诊断 zxdb 中的符号问题

变量值不可用

通常,该得分与该计划的优化级别有关:

“优化出”表示程序符号声明了具有给定名称的变量,但该变量没有值或位置。这意味着编译器已完全优化了变量,调试程序无法显示它。如果需要,请使用优化程度较低的构建设置。

不可用表示变量在当前地址无效,但其值在其他地址已知。在优化代码中,编译器通常会重复使用寄存器,破坏之前变得不可用的值。

您可以使用“sym-info”命令查看变量的有效范围:

[zxdb] sym-info my_variable
Variable: my_variable
  Type: int
  DWARF tag: 0x05
  DWARF location (address range + DWARF expression bytes):
    [0x3e0d0a3e05b, 0x3e0d0a3e0b2): 0x70 0x88 0x78
    [0x3e0d0a3e0b2, 0x3e0d0a3eb11): 0x76 0x48 0x10 0xf8 0x07 0x1c 0x06

在“DWARF 位置”下,它将给出变量值已知的地址范围列表(包括范围的起始位置,不包括结束位置)。运行到其中一个地址以查看变量的值(使用“di”可查看当前地址)。

您可以忽略“DWARF 表达式字节”,它们是用于查找变量的内部指令。

找不到符号

sym-stat 命令将告知您符号的状态。如果没有正在运行的进程,它将提供有关您指定的不同符号位置的信息。如果未找到您的符号,请确保与您的预期相符:

[zxdb] sym-stat
Symbol index status

  Indexed  Source path
 (folder)  /home/me/.build-id
 (folder)  /home/me/build/out/x64
        0  my_dir/my_file

如果您在“符号索引状态”的“已编入索引”列中看到“0”,则表示调试程序无法找到您的符号所在的位置。请参阅下文,了解如何指定这些内容的位置。

使用“.build-id”层次结构的符号源会针对已编入索引的符号列出“(folder)”,因为这类源不需要编入索引。如需检查层次结构是否包含给定的 build ID,请前往其中的“.build-id”,然后找到该 build ID 中最前面的 - 多个字符所在的文件夹,查看是否有匹配的文件。

如果您有一个正在运行的程序,sym-stat 还会针对加载到进程的每个二进制文件输出符号信息。如果没有找到符号,请在此列表中找到二进制文件或共享库的条目。如果系统显示:

    Symbols loaded: No

则表示它在本地计算机上“符号索引状态”中列出的任何位置都找不到与给定 build ID 对应的符号化二进制文件。您可能需要使用 -s 添加新位置。

如果显示如下内容:

    Symbols loaded: Yes
    Symbol file: /home/foo/bar/...
    Source files indexed: 1
    Symbols indexed: 0

其中,“已编入索引的源文件”和“已编入索引的符号”为 0 或一个非常小的整数,表示调试程序找到了符号化文件,但其中只有很少的符号或根本没有符号。通常,这意味着二进制文件未在启用符号的情况下构建,或者符号已剥离。请检查您的 build,您应该将路径传递给未剥离的二进制文件,并且原始编译行应包含用于获取符号的 -g

了解 Zxdb 如何加载符号

符号设置通常应由您的环境自动设置(请参阅下文中的关于符号设置),让大多数用户不必进行任何配置。本部分提供了一些实现详情,以帮助您诊断问题。

关于 build ID

Zxdb 使用二进制文件的“build ID”找到目标设备上二进制文件的符号。如果 build ID 不匹配,Zxdb 将不会加载这些符号,即使文件名相同也是如此。如需在 Linux 上查看二进制文件的 build ID(Mac 用户需要单独安装 readelf),请转储 ELF 二进制文件的“备注”:

$ readelf -n my_binary

  ... (some other notes omitted) ...

Displaying notes found in: .note.gnu.build-id
  Owner                Data size    Description
  GNU                  0x00000014   NT_GNU_BUILD_ID (unique build ID bitstring)
    Build ID: 18cec080fc47cdc07ec554f946f2e73d38541869

sym-stat Zxdb 命令将显示当前附加进程中加载的每个二进制文件和库的 build ID,以及对应的符号文件(如果找到)。

符号服务器

Zxdb 可以从 Google 服务器或上游 debuginfod 服务器加载预构建库的符号。如此一来,对于非本地构建的任何内容,SDK 用户都会收到符号。如需了解详情,请参阅下载符号

对于大型二进制文件,符号可能是几 GB,因此下载过程可能需要几分钟时间。 在此期间,sym-stat 命令会显示“正在下载...”。

下载的符号存储在符号缓存中。symbol-cache 设置包含此目录的名称:

[zxdb] get symbol-cache
symbol-cache = /home/me/.fuchsia/debug/symbol-cache

从从上游软件包提取的预构建二进制文件中下载符号时,debuginfo 可能没有相应的 ELF 二进制文件(具体取决于服务器和软件包)。您可能会在 zxdb 中看到如下错误:

...
binary for build_id 26820458adaf5d95718fb502d170fe374ae3ee70 not found on 5 servers
binary for build_id 53eaa845e9ca621f159b0622daae7387cdea1e97 not found on 5 servers
binary for build_id f3fd699712aae08bbaae3191eedba514c766f9d2 not found on 5 servers
binary for build_id 4286bd11475e673b194ee969f5f9e9759695e644 not found on 5 servers
binary for build_id 2d28b51427b49abcd41dcf611f8f3aa6a2811734 not found on 5 servers
binary for build_id 0401bd8da6edab3e45399d62571357ab12545133 not found on 5 servers
...

表示在 debuginfod 服务器上未找到 ELF 二进制文件。这意味着 ELF 符号将不适用于此特定二进制文件,这通常适用于大多数调试场景。在这种情况下,最常用的 ELF 特定符号是 PLT 符号。

使用 sym-stat 验证 DWARF 信息是否已加载(与 ELF 符号分开下载):

  libc.so.6
    Base: 0x1c85fdc2000
    Build ID: 0401bd8da6edab3e45399d62571357ab12545133
    Symbols loaded: Yes
    Symbol file: /home/me/.fuchsia/debug/symbol-cache/04/01bd8da6edab3e45399d62571357ab12545133.debug
    Source files indexed: 1745
    Symbols indexed: 10130

“.build-id”目录符号数据库

许多构建环境(包括主“fuchsia.git”代码库)都会在名为“.build-id”的标准目录结构中添加符号化二进制文件。此目录中包含根据二进制文件 build ID 的前两个字符命名的子目录,这些子目录中将包含根据 build ID 的其余字符命名的符号文件。

您可以在命令行中设置一个或多个 build ID 目录(无需将其命名为“.build-id”),也可以使用 build-id-dirs 设置(目录路径列表)以交互方式设置这些目录:

[zxdb] set build-id-dirs += "/home/me/project/out/x64/.build-id"

这些目录将显示在 sym-stat 命令的输出中,但会带有“(folder)”(而不是其中发现的二进制文件数量)注释,并且二进制文件不会显示在 sym-stat --dump-index 输出中。这是因为 Zxdb 会在搜索符号时按需搜索这些目录,而不是提前枚举它们。

单个文件和目录

如果您有一个二进制文件,但不包含其他符号数据库格式,则可以单独告知 Zxdb 该文件。您可以使用命令行标志,也可以使用 symbol-paths 设置(文件或目录列表)以交互方式设置该标志:

[zxdb] set symbol-paths += /home/me/project/a.out

此设置还接受目录名称。在这种情况下,Zxdb 会以非递归方式枚举该目录中的所有文件,并查找具有 build ID 的二进制文件:

[zxdb] set symbol-paths += /home/me/project/build/

如需查看您提供的营业地点的状态,请执行以下操作:

[zxdb] sym-stat
Symbol index status

  This command just refreshed the index.
  Use "sym-stat --dump-index" to see the individual mappings.

   Indexed  Source path
         1  /home/me/a.out
         2  /home/me/project/build/

您还可以使用 sym-stat --dump-index 命令查看以这种方式添加的二进制文件的 build ID 和文件名。

“ids.txt”符号索引

某些较旧的内部 Google 项目会生成名为“ids.txt”的文件。这样可以提供从二进制文件的 build ID 到本地系统上的符号路径的映射。如果您的 build 会生成此类文件,并且该文件不会自动加载,您可以通过命令行标志将其提供给 Zxdb,也可以使用 ids-txts 设置(文件名列表)以交互方式提供该文件:

[zxdb] set ids-txts += "/home/me/project/build/ids.txt"

ids.txt 文件中的符号文件也会反映在上一部分中介绍的 sym-statsym-stat --dump-index 命令中。

符号设置简介

您的环境应该会自动应用上述了解 Zxdb 如何加载符号部分中所述的设置。本部分介绍如何设置这些符号,以帮助调试符号加载问题。

symbol-index-files 设置包含一个或多个应由开发环境设置的 JSON 格式文件:

[zxdb] get symbol-index-files
symbol-index-files =
  • /home/me/.fuchsia/debug/symbol-index.json

此文件可以包含一些全局设置,还可以引用其他符号索引文件。通常,您正在使用的每个构建环境都有一个类似文件,该文件以引用方式包含在该全局文件中。如果您要在构建环境之间切换,并发现符号无法加载,请检查 ffx debug symbol-index list 命令以确保您的环境已注册。通常,当您运行任何 ffx debug ... 子工具时,它们会自动插入到包含的列表中。

源代码行不匹配

有时,源文件列表与代码不匹配。最常见的原因是 build 已过时,不再与源代码匹配。调试程序将检查符号文件的修改时间是否晚于源文件,但它仅在第一次显示文件时输出警告。如果您怀疑有问题,请查看此警告。

有些用户会多次结账。如果在错误的文件中找到了文件,请替换 build-dirs 选项,如上文设置指南中所述。

如需显示从 list 中找到的文件的文件名,请使用 -f 选项:

[zxdb] list -f
/home/me/fuchsia/out/x64/../../src/foo/bar.cc
 ... <source code> ...

您还可以设置 show-file-paths 选项。这会增加文件路径信息:

  • 它会在源代码列表中显示完整的解析路径,如 list -f 中所示。
  • 它会显示完整路径,而不只是文件名,而在其他位置(例如回溯)。
[zxdb] set show-file-paths true

在特定行上设置断点时,如果显示的断点位置与您输入的行号不匹配,您可能会注意到不匹配。在大多数情况下,这是因为此符号无法识别指定行中的任何代码,因此调试程序使用了下一行。即使是在未优化的 build 中也是如此,并且在变量声明中最常见。

[zxdb] b file.cc:138
Breakpoint 1 (Software) @ file.cc:138
   138   int my_value = 0;          <- Breakpoint was requested here.
 ◉ 139   DoSomething(&my_value);    <- But ended up here.
   140   if (my_value > 0) {