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

arm64 bt get endless main.main after nil pointer dereference #3545

Closed
fragrans1024 opened this issue Oct 31, 2023 · 2 comments · Fixed by #3559
Closed

arm64 bt get endless main.main after nil pointer dereference #3545

fragrans1024 opened this issue Oct 31, 2023 · 2 comments · Fixed by #3559

Comments

@fragrans1024
Copy link

Please answer the following before submitting your issue:

Note: Please include any substantial examples (debug session output,
stacktraces, etc) as linked gists.

If this is about source listing not showing up (or breakpoints not being
accepted) while running in a container please read our
FAQ
first.

  1. What version of Delve are you using (dlv version)?
Delve Debugger
Version: 1.21.1
Build: $Id: a358c02f24aa7047ecc562b0587dc2d08330b2cf $
  1. What version of Go are you using? (go version)?
    go version go1.20.10 linux/arm64
[root@localhost demo]# go env
GO111MODULE="off"
GOARCH="arm64"
  1. What operating system and processor architecture are you using?
    CentOS Linux release 7.9.2009 (AltArch)

  2. What did you do?

package main

func main() {
	var p_value *int = nil
	*p_value = 1
}

go build demo.go

[root@localhost demo]# dlv exec demo
Type 'help' for list of commands.
(dlv) break main.main
Breakpoint 1 set at 0x65230 for main.main() ./demo.go:5
(dlv) c
> main.main() ./demo.go:5 (hits goroutine(1):1 total:1) (PC: 0x65230)
Warning: debugging optimized function
     1: package main
     2:
     3: func main() {
     4:         var p_value *int = nil
=>   5:         *p_value = 1
     6: }
(dlv) bt
0  0x0000000000065230 in main.main
   at ./demo.go:5
1  0x000000000003d9a0 in runtime.main
   at /home/wsl/go/go1.20.10/src/runtime/proc.go:250
2  0x0000000000062e34 in runtime.goexit
   at /home/wsl/go/go1.20.10/src/runtime/asm_arm64.s:1172
(dlv) n
> [unrecovered-panic] runtime.fatalpanic() /home/wsl/go/go1.20.10/src/runtime/panic.go:1145 (hits goroutine(1):1 total:1) (PC: 0x3b680)
Warning: debugging optimized function
        runtime.curg._panic.arg: interface {}(string) "runtime error: invalid memory address or nil pointer dereference"
  1140: // fatalpanic implements an unrecoverable panic. It is like fatalthrow, except
  1141: // that if msgs != nil, fatalpanic also prints panic messages and decrements
  1142: // runningPanicDefers once main is blocked from exiting.
  1143: //
  1144: //go:nosplit
=>1145: func fatalpanic(msgs *_panic) {
  1146:         pc := getcallerpc()
  1147:         sp := getcallersp()
  1148:         gp := getg()
  1149:         var docrash bool
  1150:         // Switch to the system stack to avoid any stack growth, which
(dlv) bt
 0  0x000000000003b680 in runtime.fatalpanic
    at /home/wsl/go/go1.20.10/src/runtime/panic.go:1145
 1  0x000000000003afac in runtime.gopanic
    at /home/wsl/go/go1.20.10/src/runtime/panic.go:987
 2  0x0000000000039a78 in runtime.panicmem
    at /home/wsl/go/go1.20.10/src/runtime/panic.go:260
 3  0x000000000004fea4 in runtime.sigpanic
    at /home/wsl/go/go1.20.10/src/runtime/signal_unix.go:841
 4  0x0000000000065238 in main.main
    at ./demo.go:5
 5  0x0000000000065238 in 
    at ./demo.go:5
 6  0x0000000000065238 in main.main
    at ./demo.go:5
 7  0x0000000000065238 in main.main
    at ./demo.go:5
 8  0x0000000000065238 in main.main
    at ./demo.go:5
 9  0x0000000000065238 in main.main
    at ./demo.go:5
10  0x0000000000065238 in main.main
    at ./demo.go:5
11  0x0000000000065238 in main.main
    at ./demo.go:5
12  0x0000000000065238 in main.main
    at ./demo.go:5
13  0x0000000000065238 in main.main
    at ./demo.go:5
14  0x0000000000065238 in main.main
    at ./demo.go:5
15  0x0000000000065238 in main.main
    at ./demo.go:5
16  0x0000000000065238 in main.main
    at ./demo.go:5
17  0x0000000000065238 in main.main
    at ./demo.go:5
18  0x0000000000065238 in main.main
    at ./demo.go:5
19  0x0000000000065238 in main.main
    at ./demo.go:5
  1. What did you expect to see?
    After the nil pointer dereference, the backstrace is right.

  2. What did you see instead?
    After the nil pointer dereference, the bt is wrong with endless main.main.

@fragrans1024
Copy link
Author

Before nil pointer dereference happens, we get the SP, named SP_value_1 = 0x0000004000160770.
After nil pointer dereference happens, we get the SP again on the same frame, named SP_value_2 = 0x0000004000160760.
Two SP value for same function is different. This may be the cause of coredump endless main.main.

[root@localhost demo]# /home/wsl/gopath/bin/dlv exec demo
Type 'help' for list of commands.
(dlv) break main.main
Breakpoint 1 set at 0x65230 for main.main() ./demo.go:5
(dlv) c
> main.main() ./demo.go:5 (hits goroutine(1):1 total:1) (PC: 0x65230)
Warning: debugging optimized function
     1: package main
     2:
     3: func main() {
     4:         var p_value *int = nil
=>   5:         *p_value = 1
     6: }
(dlv) regs
 PC = 0x0000000000065230
 SP = 0x0000004000160770
 X0 = 0x0000000000065230
...
X29 = 0x0000004000160768
X30 = 0x000000000003d9a0

(dlv) n
> [unrecovered-panic] runtime.fatalpanic() /home/wsl/go/go1.20.10/src/runtime/panic.go:1145 (hits goroutine(1):1 total:1) (PC: 0x3b680)
Warning: debugging optimized function
        runtime.curg._panic.arg: interface {}(string) "runtime error: invalid memory address or nil pointer dereference"
  1140: // fatalpanic implements an unrecoverable panic. It is like fatalthrow, except
  1141: // that if msgs != nil, fatalpanic also prints panic messages and decrements
  1142: // runningPanicDefers once main is blocked from exiting.
  1143: //
  1144: //go:nosplit
=>1145: func fatalpanic(msgs *_panic) {
  1146:         pc := getcallerpc()
  1147:         sp := getcallersp()
  1148:         gp := getg()
  1149:         var docrash bool
  1150:         // Switch to the system stack to avoid any stack growth, which
(dlv) bt
 0  0x000000000003b680 in runtime.fatalpanic
    at /home/wsl/go/go1.20.10/src/runtime/panic.go:1145
 1  0x000000000003afac in runtime.gopanic
    at /home/wsl/go/go1.20.10/src/runtime/panic.go:987
 2  0x0000000000039a78 in runtime.panicmem
    at /home/wsl/go/go1.20.10/src/runtime/panic.go:260
 3  0x000000000004fea4 in runtime.sigpanic
    at /home/wsl/go/go1.20.10/src/runtime/signal_unix.go:841
 4  0x0000000000065238 in main.main
    at ./demo.go:5
 5  0x0000000000065238 in main.main
    at ./demo.go:5
 6  0x0000000000065238 in main.main
    at ./demo.go:5
 7  0x0000000000065238 in main.main
    at ./demo.go:5
 8  0x0000000000065238 in main.main
    at ./demo.go:5
(dlv) frame 4
> [unrecovered-panic] runtime.fatalpanic() /home/wsl/go/go1.20.10/src/runtime/panic.go:1145 (hits goroutine(1):1 total:1) (PC: 0x3b680)
Warning: debugging optimized function
Frame 4: ./demo.go:5 (PC: 65238)
     1: package main
     2:
     3: func main() {
     4:         var p_value *int = nil
=>   5:         *p_value = 1
     6: }
(dlv) regs
 PC = 0x0000000000065238
 SP = 0x0000004000160760
X29 = 0x0000004000160768
X30 = 0x0000000000065238

(dlv) frame 5
> [unrecovered-panic] runtime.fatalpanic() /home/wsl/go/go1.20.10/src/runtime/panic.go:1145 (hits goroutine(1):1 total:1) (PC: 0x3b680)
Warning: debugging optimized function
Frame 5: ./demo.go:5 (PC: 65238)
     1: package main
     2:
     3: func main() {
     4:         var p_value *int = nil
=>   5:         *p_value = 1
     6: }
(dlv) regs
 PC = 0x0000000000065238
 SP = 0x0000004000160760
X29 = 0x0000004000160768
X30 = 0x0000000000065238

(dlv)

@fragrans1024
Copy link
Author

fragrans1024 commented Nov 20, 2023

@derekparker
@aarzilli
We test the commit, the SP is wrong.
We add some test, some core can not get the right frame. The following is the test code.

package main

import "fmt"

func main() {
	map_value := make(map[string]*int)

	var value_1 int = 1
	var value_2 int = 2
	map_value["a"] = &value_1
	map_value["b"] = &value_2

	for key, value := range map_value {
		fmt.Printf("key = %s, value = %d\n", key, *value)
	}

	mod_map(map_value)

	for key, value := range map_value {
		fmt.Printf("key = %s, value = %d\n", key, *value)
	}
}

func mod_map(map_value map[string]*int) {
	p_value := map_value["c"]
	*p_value = 3
}

The dlv get the frame stack:

[root@localhost demo2]# /home/wsl/gopath/bin/dlv core demo_2 core_demo_2_79139
Type 'help' for list of commands.
(dlv) bt
 0  0x000000000006cb58 in runtime.raise
    at /home/wsl/go/go1.20.10/src/runtime/sys_linux_arm64.s:158
 1  0x0000000000054914 in runtime.dieFromSignal
    at /home/wsl/go/go1.20.10/src/runtime/signal_unix.go:883
 2  0x0000000000054e18 in runtime.sigfwdgo
    at /home/wsl/go/go1.20.10/src/runtime/signal_unix.go:1096
 3  0x000000000005391c in runtime.sigtrampgo
    at /home/wsl/go/go1.20.10/src/runtime/signal_unix.go:432
 4  0x000000000006cb58 in runtime.raise
    at /home/wsl/go/go1.20.10/src/runtime/sys_linux_arm64.s:157
 5  0x0000000000054914 in runtime.dieFromSignal
    at /home/wsl/go/go1.20.10/src/runtime/signal_unix.go:883
 6  0x000000000003fd78 in runtime.crash
    at /home/wsl/go/go1.20.10/src/runtime/signal_unix.go:975
 7  0x000000000003fd78 in runtime.fatalpanic
    at /home/wsl/go/go1.20.10/src/runtime/panic.go:1172
 8  0x000000000003f63c in runtime.gopanic
    at /home/wsl/go/go1.20.10/src/runtime/panic.go:987
 9  0x000000000003e098 in runtime.panicmem
    at /home/wsl/go/go1.20.10/src/runtime/panic.go:260
10  0x0000000000054894 in runtime.sigpanic
    at /home/wsl/go/go1.20.10/src/runtime/signal_unix.go:841
11  0x000000000008f45c in main.mod_map
    at ./demo_2.go:26
12  0x000000000008f45c in main.main
    at ./demo_2.go:17
13  0x000000000008f45c in main.mod_map
    at ./demo_2.go:26
14  0x000000000008f45c in main.main
    at ./demo_2.go:17
15  0x000000000008f454 in main.mod_map
    at ./demo_2.go:25
16  0x000000000008f454 in main.main
    at ./demo_2.go:17

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants