診斷 zxdb 中的符號問題

無法使用變數值

這通常與計畫的最佳化等級有關:

「最佳化」表示程式符號使用指定名稱宣告變數,但該變數沒有值或位置。這表示編譯器已全面最佳化變數,偵錯工具無法顯示該變數。如果需要,請使用最佳化程度較低的建構設定。

「Unavailable」表示變數在目前地址無效,但在其他位址中知道變數的值。在最佳化程式碼中,編譯器通常會重複使用暫存器,規避先前的值,但這些值將無法使用。

您可以使用「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」階層的符號來源會列出已建立索引符號的「(資料夾)」,因為這類來源不需要建立索引。如要檢查階層是否包含特定的建構 ID,請前往其中「.build-id」,然後點選含有建構 ID 第一個字元的資料夾,看看是否存在相符的檔案。

當您有執行中的程式時,sym-stat 會另外列印載入程序中的每個二進位檔的符號資訊。如果您未取得符號,請在清單中找出二進位檔或共用資料庫的項目。請根據以下狀態採取相應行動:

    Symbols loaded: No

那就代表在「符號索引狀態」中列出的任何位置,在電腦上找不到指定版本 ID 的符號化二進位檔。您可能需要使用 -s 新增地點。

而是如下所示:

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

「已建立索引的來源檔案」和「已建立索引的符號」為 0 或極低的整數,表示偵錯工具找到一個符號化檔案,但裡面少了或完全沒有符號。通常這表示未使用符號建構二進位檔,或是符號已移除。檢查建構,您應將路徑傳遞至未去除的二進位檔,而原始編譯行內應含有 -g,才能取得符號。

瞭解 Zxdb 如何載入符號

通常,您的環境應會自動設定符號設定 (請參閱下方的關於符號設定),這樣多數使用者都不需要做任何設定。本節提供一些實作詳細資料,協助您診斷問題。

關於版本 ID

Zxdb 會根據二進位檔的「版本 ID」,在目標裝置上找出二進位檔的符號。如果版本 ID 不相符,Zxdb 將不會載入符號,即使檔案名稱相同也一樣。如要查看 Linux 二進位檔的建構 ID (Mac 使用者必須單獨安裝 Readelf),請傾印 ELF 二進位檔的「notes」:

$ 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 指令會顯示目前附加程序中載入的每個二進位檔和程式庫的建構 ID,如果找到,則會顯示對應的符號檔案。

符號伺服器

Zxdb 可以從 Google 伺服器或上游偵錯伺服器載入預建程式庫的符號。這會為 SDK 使用者顯示未在本機建構任何項目的符號。詳情請參閱「下載符號」。

大型二進位檔的符號檔案可能會幾 GB,因此下載程序可能需要幾分鐘才能完成。 在這段期間,sym-stat 指令會顯示「下載中...」。

下載的符號會儲存在符號快取中。symbol-cache 設定包含此目錄的名稱:

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

從預先建構的二進位檔從上游套件下載符號時,偵錯資訊可能不會有對應的 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
...

在偵錯資訊伺服器上找不到 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」的標準目錄結構中新增符號化二進位檔。這個目錄包含子目錄,並依據二進位檔版本 ID 的前兩個字元命名,而這些目錄內將是依據建構 ID 中其餘字元命名的符號檔案。

您可以在指令列中設定一或多個建構 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 會以非遞迴方式列舉該目錄中的所有檔案,並尋找具有建構 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 指令查看透過這種方式新增的二進位檔的建構 ID 和檔案名稱。

「ids.txt」符號索引

某些較舊的 Google 內部專案會產生名為「ids.txt」的檔案。這可提供從二進位檔的版本 ID 與本機系統符號路徑之間的對應關係。如果您的版本產生這類檔案,而且檔案並未自動載入,您可以透過指令列標記提供檔案給 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-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

如果在特定行上設定中斷點的位置,其中顯示的中斷點位置與您輸入的行編號不符,您可能會注意到不相符。在大多數情況下,這是因為這個符號在指定的行上沒有識別任何程式碼,所以偵錯工具會使用下一行。即使是在未最佳化的建構作業中也會發生,而且最常見的變數宣告是最常見的情況。

[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) {