提问人:user38643 提问时间:1/25/2023 最后编辑:Zeke Luuser38643 更新时间:5/13/2023 访问量:966
无法使用 delve 评估 Go 调试中的函数
Unable to evaluate functions in Go debugging using delve
问:
我在 M1 Mac(ARM64 芯片)上,但仍然无法通过使用 DLV 后端的 VSCode 中的调试器调用函数。
调试控制台
call test()
Unable to evaluate expression: could not find symbol value for test
test()
Unable to evaluate expression: function calls not allowed without using 'call'
我正在使用最新的 DLV:
~ ❯ dlv version
Delve Debugger
Version: 1.20.1
Build: $Id: 96e65b6c615845d42e0e31d903f6475b0e4ece6e
我错过了什么?
答:
如果你的函数在一个文件中,除非你的一个函数调用它,否则它实际上可能并不存在——我发现我的代码也是如此。test
*_test.go
Test*
似乎可能正在剥离测试代码未调用的函数。go
这很可能是由于死代码消除造成的。接下来是从 cmd/link/internal/ld/deadcode.go 复制的文档:
消除死代码的基础是符号的泛滥, 搬迁后,从 .
*flagEntrySymbol
此泛滥填充包装在用于修剪未使用方法的逻辑中。 所有方法都通过其接收器上的重定位来提及。 这些重定位由编译器专门定义 因此,我们可以在这里检测和操纵它们。
*rtype
R_METHODOFF
可访问类型的方法有三种方式:
- 直接通话
- 通过可访问的接口类型
- 反映。Value.Method(或 MethodByName)或 reflect。Type.Method (或 MethodByName)
第一种情况由洪水填充处理,这是一种直接调用的方法 标记为可访问。
第二种情况是通过分解所有可访问的接口来处理的 类型添加到方法签名中。比较遇到的每种方法 针对接口方法签名,如果匹配,则标记 可访问。这是非常保守的,但简单而正确。
第三种情况是通过查看是否有任何一种情况来处理的:
reflect.Value.Method
或可访问MethodByName
reflect.Type.Method
或被调用(通过编译器标记的属性)。MethodByName
REFLECTMETHOD
如果发生上述任何一种情况,则所有赌注都将关闭,所有导出的方法都将关闭 的可访问类型标记为可访问。
将从 ctxt 中删除任何未到达的文本符号
。文本。
例如,下面的 func 是死代码,将被删除。test
package main
import (
"fmt"
)
func main() {
fmt.Println("Hello world!")
}
func test() string {
return "test"
}
我们可以通过以下方式验证消除:go tool nm
$ go build -gcflags="all=-N -l" -o main main.go
$ go tool nm main | grep -F " main."
524000 D main..inittask
49cbc0 T main.main
在这种情况下失败了。call test()
现在让我们添加:var _ = test()
+ var _ = test()
func test() string {
return "test"
}
然后再试一次:
$ go build -gcflags="all=-N -l" -o main main.go
go tool nm main | grep -F " main."
524720 D main..inittask
49cc80 T main.init
49cbc0 T main.main
49cc40 T main.test
这次我们有了这个符号。并工作:main.test
call test()
$ dlv debug main.go 36s 00:36:33
Type 'help' for list of commands.
(dlv) c main.main
Breakpoint 1 set at 0x49cbc6 for main.main() ./main.go:7
> main.main() ./main.go:7 (hits goroutine(1):1 total:1) (PC: 0x49cbc6)
2:
3: import (
4: "fmt"
5: )
6:
=> 7: func main() {
8: fmt.Println("Hello world!")
9: }
10:
11: var _ = test()
12: func test() string {
(dlv) n
> main.main() ./main.go:8 (PC: 0x49cbd4)
3: import (
4: "fmt"
5: )
6:
7: func main() {
=> 8: fmt.Println("Hello world!")
9: }
10:
11: var _ = test()
12: func test() string {
13: return "test"
(dlv) call test()
> main.main() ./main.go:8 (PC: 0x49cbd4)
Values returned:
~r0: "test"
评论