go: cmd/compile: bad inlining tree emitted for function literal

What version of Go are you using (go version)?

$ go version
go version devel go1.17-8b0901fd32 Tue May 18 07:50:25 2021 +0000 linux/amd64

Does this issue reproduce with the latest release?

Only on 1.17 / tip – this problem is not present in 1.16.

What operating system and processor architecture are you using (go env)?

linux/amd64

What did you do?

Run this program: https://play.golang.org/p/VZWvwkvYUGx

What did you expect to see?

In 1.16 you get a crash on a nil pointer, e.g.

$ go run repro.go
begin main
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x4a2245]

goroutine 1 [running]:
main.WEA.func1(0x0)
	/tmp/repro.go:17 +0x5
main.(*CM).NewA(0xc0000eef40, 0x0, 0x0, 0x4c761f, 0x3, 0x0, 0xc0000eeed0, 0x2, 0x2, 0xb, ...)
	/tmp/repro.go:30 +0x42
main.(*R).CA(0xc0000eef48, 0x0, 0x0, 0x4c761f, 0x3, 0x0, 0x0, 0xb, 0x0)
	/tmp/repro.go:37 +0xd1
main.main()
	/tmp/repro.go:52 +0xc5
exit status 2
thanm@cetina:/tmp$ 

What did you see instead?

Program gets an infinite loop in traceback:

begin main
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x487f00]

goroutine 1 [running]:
main.WEA(...)
        /tmp/repro.go:17
main.WEA(...)
        /tmp/repro.go:17
main.WEA(...)
        /tmp/repro.go:17
main.WEA(...)
        /tmp/repro.go:17
<repeats>

The problem sees to be in the runtime’s traceback handling of inlining – at the point of the fault we are at

Dump of assembler code for function main.(*R).CA.func1:
=> 0x0000000000487f00 <+0>:	movb   $0x1,(%rax)
   0x0000000000487f03 <+3>:	retq   

The inlining tree for this function (from go build -gcflags=-d=pctab=pctoinline) looks like

-- inlining tree for "".(*R).CA.func1:
0 | -1 | "".WEA (/tmp/repro.go:37:39) pc=0

The problem here is that the traceback code is trying to “back up” an instruction when landing on 0x0000000000487f00 to recover the parent PC (runtime code here), but this winds up hitting the same instruction, hence we never get out of the loop.

I’m tentatively marking this as a compiler bug, can be retitled if it turns out there are other components involved.

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 20 (17 by maintainers)

Commits related to this issue

Most upvoted comments

It shows up in the dump. For example in this code:

func (r *R) CA(ctx context.Context, cN string, nn *nAO) (*int, error) {
	cA, err := r.cM.NewA(ctx, cN, nn, WEA(), WEA())
	if err == nil {

the calls to WEA() get inlined. In the dump you can see this in the second column:

    39        00057 (<unknown line number>)	NOP
    39        00057 (/usr/local/google/home/thanm/gobugs/46234/repro.go:37)	XORL	AX, AX
    3b      0 00059 (/usr/local/google/home/thanm/gobugs/46234/repro.go:37)	JMP	96
    3d        00061 (/usr/local/google/home/thanm/gobugs/46234/repro.go:37)	MOVQ	AX, main..autotmp_36+8(SP)
    42        00066 (/usr/local/google/home/thanm/gobugs/46234/repro.go:37)	MOVQ	main..autotmp_24+24(SP)(AX*8), DX

Note the “0” for the instruction at 00059.

At least that’s how I’m reading it; hopefully I am not off base.

@cherrymui I was able to confirm that the loop does go infinite. We only check the n < max condition at the top-level, whereas the inner loop for handling PCDATA_InlTreeIndex goes until it finds a negative value (which never happens with a cycle).