go cmd/compile: 变量的DWARF位置错误

ffdz8vbo  于 5个月前  发布在  Go
关注(0)|答案(5)|浏览(52)

给定以下代码:

package main

import "fmt"

func cul(row int64) bool {
	id := int((row >> 32) & 0x3fffffff)
	
	return id != 0
}

func main() {
	fmt.Println(cul(0))
}

使用`-gcflags='all=-N -l', main.cul函数编译成:

test.go:5		0x49c8c0		4883ec18		SUBQ $0x18, SP		
  test.go:5		0x49c8c4		48896c2410		MOVQ BP, 0x10(SP)	
  test.go:5		0x49c8c9		488d6c2410		LEAQ 0x10(SP), BP	
  test.go:5		0x49c8ce		4889442420		MOVQ AX, 0x20(SP)	
  test.go:5		0x49c8d3		c644240700		MOVB $0x0, 0x7(SP)	
  test.go:6		0x49c8d8		488b4c2420		MOVQ 0x20(SP), CX	
  test.go:6		0x49c8dd		48c1f920		SARQ $0x20, CX		
  test.go:6		0x49c8e1		81e1ffffff3f		ANDL $0x3fffffff, CX	
  test.go:8		0x49c8e7		4885c9			TESTQ CX, CX		
  test.go:8		0x49c8ea		0f95c0			SETNE AL		
  test.go:6		0x49c8ed		48894c2408		MOVQ CX, 0x8(SP)	
  test.go:8		0x49c8f2		88442407		MOVB AL, 0x7(SP)	
  test.go:8		0x49c8f6		488b6c2410		MOVQ 0x10(SP), BP	
  test.go:8		0x49c8fb		4883c418		ADDQ $0x18, SP		
  test.go:8		0x49c8ff		90			NOPL			
  test.go:8		0x49c900		c3			RET

变量id有其位置,但是在指令0x49c8ea(这是为第:8行设置断点的指令)处,该变量存储在寄存器rcx中,而不是在其堆栈位置(稍后在该指令0x49c8ed处才移动)。
最初报告为go-delve/delve#3290
cc @dr2chase.

9wbgstp7

9wbgstp71#

CC @golang/compiler.

fcwjkofz

fcwjkofz2#

在紧急情况下,@dr2chase已分配给您,因为我们需要您的输入,但请随时取消分配。

ars1skjm

ars1skjm3#

我认为这个"自动修复"并不是一个令人满意的解决方案。一个更持久的解决办法是在-N编译时分配行号时,注意应该早些进行的赋值操作,并确保它们确实已经完成并存储在内存中。我希望将这个问题留待下一次发布时解决,因为这个修复实际上有点复杂。

8mmmxcuj

8mmmxcuj4#

如果这有帮助的话,这里是从 this stackoverflow question 中提取的另一个案例:

1	package main
 2	
 3	func main() {
 4		a := f(1)
 5		b := 1
 6	
 7		c := a < b
 8		_ = c
 9	}
10	
11	func f(i int) int {
12		if i > 0 {
13			return i
14		}
15		return -i
16	}

这是 delve debug 会话的输出:

(dlv) l
> main.main() ./main.go:7 (hits goroutine(1):1 total:1) (PC: 0x4608de)
     2:	
     3:	func main() {
     4:		a := f(1)
     5:		b := 1
     6:	
=>   7:		c := a < b
     8:		_ = c
     9:	}
    10:	
    11:	func f(i int) int {
    12:		if i > 0 {
(dlv) disass
TEXT main.main(SB) /home/zeke/src/temp/76380802/main.go
	main.go:3	0x4608c0	493b6610		cmp rsp, qword ptr [r14+0x10]
	main.go:3	0x4608c4	7639			jbe 0x4608ff
	main.go:3	0x4608c6	4883ec28		sub rsp, 0x28
	main.go:3	0x4608ca	48896c2420		mov qword ptr [rsp+0x20], rbp
	main.go:3	0x4608cf	488d6c2420		lea rbp, ptr [rsp+0x20]
	main.go:4	0x4608d4	b801000000		mov eax, 0x1
	main.go:4	0x4608d9	e842000000		call $main.f
=>	main.go:7	0x4608de*	4883f801		cmp rax, 0x1
	main.go:4	0x4608e2	4889442418		mov qword ptr [rsp+0x18], rax
	main.go:5	0x4608e7	48c744241001000000	mov qword ptr [rsp+0x10], 0x1
	main.go:7	0x4608f0	0f9c44240f		setl byte ptr [rsp+0xf]
	main.go:9	0x4608f5	488b6c2420		mov rbp, qword ptr [rsp+0x20]
	main.go:9	0x4608fa	4883c428		add rsp, 0x28
	main.go:9	0x4608fe	c3			ret
	main.go:3	0x4608ff	90			nop
	main.go:3	0x460900	e83bccffff		call $runtime.morestack_noctxt
	main.go:3	0x460905	ebb9			jmp $main.main
(dlv) locals
a = 824633745824
b = 824633843808
8fsztsew

8fsztsew5#

另一个例子,这个是针对arm64的:

package main

import "fmt"

func main() {
        SimpleMethodWithArgument(0)
}

//go:noinline
func SimpleMethodWithArgument(i int) {
        a := 5
        y := 10
        x := a + y + i // Breakpoint here
        fmt.Printf("a: %v, y: %v\n", a, y)
        _ = x
        return
}

SimpleMethodWithArguments 编译后为:
| test.go:10 | S | 0x4977c0 | 4c8d6424e8 | LEAQ -0x18(SP), R12 |
| ------------ | ------------ | ------------ | ------------ | ------------ |
| test.go:10 | | 0x4977c5 | 4d3b6610 | CMPQ 0x10(R14), R12 |
| test.go:10 | | 0x4977c9 | 0f8615010000 | JBE 0x4978e4 |
| test.go:10 | | 0x4977cf | 55 | PUSHL BP |
| test.go:10 | | 0x4977d0 | 4889e5 | MOVQ SP, BP |
| test.go:10 | SP | 0x4977d3 | 4881ec90000000 | SUBQ $0x90, SP |
| test.go:10 | | 0x4977da | 48898424a0000000 | MOVQ AX, 0xa0(SP) |
| test.go:11 | S | 0x4977e2 | 48c744243805000000 | MOVQ $0x5, 0x38(SP) |
| test.go:12 | S | 0x4977eb | 48c74424280a000000 | MOVQ $0xa, 0x28(SP) |
| test.go:13 | S | 0x4977f4 | 488d480f | LEAQ 0xf(AX), CX |
| test.go:13 | | 0x4977f8 | 48894c2430 | MOVQ CX, 0x30(SP) |
| test.go:14 | S | 0x4977fd | 440f117c2470 | MOVUPS X15, 0x70(SP) |
在地址 0x4977d3,第一个语句中,栈变量尚未初始化。

相关问题