调试 go 代码(状态报告)

Debugging Go code (a status report) - 调试 go 代码(状态报告)

https://go.dev/blog/debug-status

Luuk van Dijk 2 November 2010

2010 年 11 月 2 日

​ 在调试方面,有一些策略性的打印语句来检查变量或一个恰当放置的 panic 来获得堆栈跟踪是无可比拟的。但是,有时您要么没有耐心要么没有源代码,在这种情况下,一个好的调试器就会变得非常有价值。这就是为什么在过去的几个版本中,我们一直在改进 Go 的 gc 链接器(6l, 8l)对 GNU 调试器 GDB 的支持。

​ 在最新版本(2010-11-02)中,6l 和 8l 链接器在写 ELF(Linux、FreeBSD)或 Mach-O(Mac OS X)二进制文件时会发出 DWARF3 调试信息。DWARF 代码足够丰富,可以让您做以下事情:

  • 在 GDB 版本 7.x 中加载 Go 程序,

  • 按行列出所有 Go、C 和汇编源文件(Go 运行时的部分是用 C 和汇编语言编写的),

  • 按行设置断点并逐步执行代码,

  • 打印堆栈跟踪并检查堆栈帧,

  • 查找大多数变量的地址并打印其内容。

仍有一些不便之处:

  • 发出的 DWARF 代码无法被 Mac OS X 附带的 GDB 版本 6.x 读取。我们很乐意接受补丁,使 DWARF 输出与标准 OS X GDB 兼容,但在此之前,您需要下载、构建并安装 GDB 7.x 才能在 OS X 下使用它。源代码可以在 http://sourceware.org/gdb/download/ 找到。由于 OS X 的特殊性,您需要在本地文件系统上安装二进制文件,然后使用 chgrp procmod 和 chmod g+s 命令设置权限。
  • 名称是带有包名称的限定符,而 GDB 不理解 Go 包,因此必须使用完整名称引用每个项目。例如,包 main 中名为 v 的变量必须称为 ‘main.v’,使用单引号。这样做的结果是变量和函数名称的制表符自动完成无法工作。
  • 词法作用域信息有些模糊。如果有多个同名变量,则第 n 个实例将具有形式为‘#n’的后缀。我们计划修复这个问题,但这需要对编译器和链接器之间交换的数据进行一些更改。
  • 切片和字符串变量表示为运行时库中的底层结构。它们将看起来像 {data = 0x2aaaaab3e320,len = 1,cap = 1}。对于切片,您必须解引用数据指针以检查元素。

有些东西还没有完全实现:

  • 无法检查通道、函数、接口和映射变量。
  • 只有 Go 变量带有类型信息;运行时的 C 变量没有。
  • Windows 和 ARM 二进制文件不包含 DWARF 调试信息,因此无法使用 GDB 进行检查。

​ 在未来几个月中,我们打算通过更改编译器和链接器或使用 GDB 的 Python 扩展来解决这些问题。同时,我们希望 Go 程序员能从这个著名的调试工具中获得更好的访问权限。

​ 补充说明:DWARF 信息也可以被除 GDB 以外的工具读取。例如,在 Linux 上,您可以将其与 sysprof 系统范围分析器一起使用。。