天天看點

Hexagon GDB Debugger介紹(5)

Hexagon GDB Debugger介紹(5)

      • 2.5.4 shell 指令
      • 2.5.5 Tcl 腳本
      • 2.5.6 記錄輸出
      • 2.5.7 獲得幫助
      • 2.5.8 示例調試會話

2.5.4 shell 指令

如果你需要在調試會話期間偶爾執行 shell 指令,則無需離開或暫停調試器; 相反,你可以使用 shell 指令。

shell 指令字元串

調用标準 shell 來執行 command_string。 如果存在,環境變量 SHELL 決定運作哪個 shell。 否則,調試器将使用預設 shell(例如,UNIX 系統上的 /bin/sh)。

在開發環境中經常需要實用程式 make。 為此,你不必使用 shell 指令。 例如:

make make_args

… 使用指定的參數執行 make 程式。 這相當于“shell make make_args”。

2.5.5 Tcl 腳本

調試器可選擇支援使用 Tcl 腳本語言。 可以使用 set 指令啟用 Tcl 腳本。

set tclfe on
啟用 Tcl 腳本(第 4.4 節)。
注意
    啟用腳本會影響 GDB 指令縮寫(第 2.5.1 節)
           

2.5.6 記錄輸出

你可能希望将調試器指令的輸出儲存到檔案中。 有幾個指令可以控制日志記錄。

指令 描述
set logging on 啟用日志記錄。
set logging off 禁用日志記錄。
set logging file file 更改目前日志檔案的名稱。 預設日志檔案是 gdb.txt。
set logging overwrite [on|off] 預設情況下,調試器會将新的日志資訊附加到日志檔案中。 如果你希望将登入設定為覆寫日志檔案,請設定覆寫。
set logging redirect [on|off] 預設情況下,調試器輸出同時寫入終端和日志檔案。 如果你隻想輸出到日志檔案,請設定重定向。
show logging 顯示日志設定的目前值。

2.5.7 獲得幫助

你始終可以使用指令幫助向調試器詢問有關其指令的資訊。

指令 描述
help / h 可以使用不帶參數的幫助(縮寫為 h)來顯示命名指令類的簡短清單。
help class 使用通用幫助類之一作為參數,可以獲得該類中各個指令的清單。 例如,這裡是class狀态的幫助顯示:
(hexagon-gdb) help status
 狀态查詢。
 指令清單:
 info -- 用于顯示有關正在調試的程式的資訊的通用指令

 show -- 用于顯示有關調試器的内容的通用指令
 鍵入“help”後跟指令名稱以擷取完整文檔。

 如果沒有歧義,則允許使用指令名稱縮寫。
           
指令 描述
help command 使用指令名稱作為幫助參數,顯示關于如何使用該指令的簡短段落。
apropos command_expr apropos 指令在所有調試器指令及其相應文檔中搜尋 command_expr 中指定的正規表達式。 它列印出找到的所有比對項。 例如:
apropos reload
 ... 結果是: 
 set symbol-reloading -- 在一次運作中設定動态符号表重新加載多次

 show symbol-reloading -- 在一次運作中顯示多次重新加載的動态符号表
           
指令 描述
complete command_string complete 指令列出了指令開頭的所有可能的補全。 使用 command_string 指定要完成的指令的開頭。 例如:
complete i
... results in: 
if
ignore
info

inspec
NOTE complete 旨在供 GNU Emacs 使用。

           

除了幫助之外,還可以使用指令 info 和 show 來查詢程式的狀态或調試器本身的狀态。 每個指令支援多個查詢主題; 本手冊在适當的上下文中介紹了它們中的每一個。

指令 描述
info 此指令(縮寫為 i)用于描述程式的狀态。 例如,可以使用 info args 列出給你的程式的參數,使用 info registers 列出目前正在使用的寄存器,或者列出你使用 info breakpoints 設定的斷點。 你可以通過幫助資訊擷取資訊子指令的完整清單。
set 你可以使用 set 将表達式的結果配置設定給環境變量。 例如,你可以使用 set prompt $ 将調試器提示設定為 $-sign。
show 與 info 不同,show 用于描述調試器本身的狀态。 通過使用相關的指令集,你可以更改你可以顯示的大部分内容; 例如,你可以使用 set radix 控制顯示使用的數字系統,或者隻需使用 show radix 查詢目前正在使用的數字系統。 要顯示所有可設定的參數及其目前值,你可以使用不帶參數的 show; 你也可以使用資訊集。 這兩個指令産生相同的顯示。

以下是三個雜項 show 子指令,所有這些子指令都缺少相應的 set 指令:

指令 描述
show version 顯示正在運作的調試器版本。
show copying 顯示有關複制調試器的權限的資訊。
show warranty 顯示 GNU “NO WARRANTY”聲明或保證(如果你的調試器版本附帶有)。

2.5.8 示例調試會話

本節提供了一個示例調試會話,它示範了基本的調試器指令。

gnu m4(一種通用宏處理器)的一個初步版本顯示出以下錯誤:有時,當我們從預設值更改其引号字元串時,用于捕獲另一個宏定義中的指令的指令會停止工作。 在以下簡短的 m4 會話中,我們定義了一個宏 foo,它擴充為 0000; 然後我們使用 m4 内置的 defn 将 bar 定義為相同的東西。 但是,當我們将左引号字元串更改為 并将關閉引号字元串更改為 時,相同的過程無法定義新的同義詞 baz:

$ cd gnu/m4
$ ./m4
define(foo,0000)
foo
0000

define(bar,defn(’foo’))
bar
0000
changequote(<QUOTE>,<UNQUOTE>)
define(baz,defn(<QUOTE>foo<UNQUOTE>))
baz

Ctrl-d

m4: End of input: 0: fatal error: EOF in string
           

要查找 m4 中的錯誤,請啟動調試器:

$ hexagon-gdb
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
(hexagon-gdb)
           

調試器隻讀取足夠的符号資料,以便在需要時知道在哪裡可以找到其餘的; 結果,第一個提示出現得非常快。 我們現在告訴它使用比平時更窄的顯示寬度,以便示例适合本手冊。

(hexagon-gdb) set width 70
           

我們需要看看 m4 内置的 changequote 是如何工作的。 檢視源代碼後,我們知道相關子程式是 m4_changequote,是以我們使用 break 指令在那裡設定了一個斷點。

(hexagon-gdb) break m4_changequote
Breakpoint 1 at 0x62f4: file builtin.c, line 879.
           

使用 run 指令,我們啟動 m4 在調試器的控制下運作; 隻要控制沒有到達 m4_changequote 子程式,程式就照常運作:

(hexagon-gdb) run
Starting program: /work/Editorial/gdb/gnu/m4/m4

define(foo,0000)
foo
0000
           

為了觸發斷點,我們調用changequote。 調試器暫停 m4 的執行,顯示有關它停止的上下文的資訊。

changequote(<QUOTE>,<UNQUOTE>)
Breakpoint 1, m4_changequote (argc=3, argv=0x33c70)
  at builtin.c:879
879         if (bad_argc(TOKEN_DATA_TEXT(argv[0]),argc,1,3))
           

現在我們使用指令 n (next) 将執行推進到目前函數的下一行。

(hexagon-gdb) n
882    set_quotes((argc >= 2) ? TOKEN_DATA_TEXT(argv[1])\
 : nil,
           

set_quotes 看起來像是一個很有前途的子程式。 我們可以使用指令 s (step) 而不是 next 來進入它。 step 轉到要在任何子例程中執行的下一行,是以它步入 set_quotes。

(hexagon-gdb) s
set_quotes (lq=0x34c78 "<QUOTE>", rq=0x34c88 "<UNQUOTE>")

at input.c:530

530         if (lquote != def_lquote)
           

顯示 m4 現在挂起的子程式(及其參數)的顯示稱為堆棧幀顯示。 它顯示了堆棧的摘要。 我們可以使用 backtrace 指令(也可以拼寫為 bt)來檢視我們在整個堆棧中的位置:backtrace 指令顯示每個活動子程式的堆棧幀。

(hexagon-gdb) bt
#0  set_quotes (lq=0x34c78 "<QUOTE>", rq=0x34c88 "<UNQUOTE>")

at input.c:530
#1  0x6344 in m4_changequote (argc=3, argv=0x33c70)
at builtin.c:882
#2  0x8174 in expand_macro (sym=0x33320) at macro.c:242
#3  0x7a88 in expand_token (obs=0x0, t=209696, td=0xf7fffa30)
at macro.c:71
#4  0x79dc in expand_input () at macro.c:40
#5  0x2930 in main (argc=0, argv=0xf7fffb20) at m4.c:195
           

我們再多走幾行看看會發生什麼。 前兩次,我們可以使用s; 接下來的兩次我們使用 n 來避免陷入 xstrdup 子例程。

(hexagon-gdb) s
0x3b5c  532         if (rquote != def_rquote)

(hexagon-gdb) s
0x3b80  535         lquote = (lq == nil || *lq == ’\0’) ?  \

def_lquote : xstrdup(lq);

(hexagon-gdb) n
536         rquote = (rq == nil || *rq == ’\0’) ? def_rquote\
 : xstrdup(rq);

(hexagon-gdb) n
538         len_lquote = strlen(rquote);
           

顯示的最後一行看起來有點奇怪; 我們可以檢查變量 lquote 和 rquote 以檢視它們是否實際上是我們指定的新左引号和右引号。 我們使用指令 p(列印)來檢視它們的值。

(hexagon-gdb) p lquote
$1 = 0x35d40 "<QUOTE>"
(hexagon-gdb) p rquote
$2 = 0x35d50 "<UNQUOTE>"
           

lquote 和 rquote 确實是新的左右引号。 為了檢視一些上下文,我們可以使用 l (list) 指令顯示圍繞目前行的十行源代碼。

(hexagon-gdb)  l
533        xfree(rquote);
534
535         lquote = (lq == nil || *lq == ’\0’) ? def_lquote\
 : xstrdup (lq);
536         rquote = (rq == nil || *rq == ’\0’) ? def_rquote\

 : xstrdup (rq);
537
538         len_lquote = strlen(rquote);
539         len_rquote = strlen(lquote);
540     }
541
542     void
           

讓我們跳過設定 len_lquote 和 len_rquote 的兩行,并檢查這些變量的值。

(hexagon-gdb) n
539         len_rquote = strlen(lquote);

(hexagon-gdb) n
540     }

(hexagon-gdb) p len_lquote
$3 = 9
(hexagon-gdb) p len_rquote
$4 = 7
           

這看起來肯定是錯誤的,假設 len_lquote 和 len_rquote 分别是 lquote 和 rquote 的長度。 我們可以使用 p 指令将變量設定為更好的值,因為它可以列印任何表達式的值,并且該表達式可以包括子例程調用和指派。

(hexagon-gdb)  p len_lquote=strlen(lquote)
$5 = 7

(hexagon-gdb)  p len_rquote=strlen(rquote)
$6 = 9
           

這足以解決在 m4 内置 defn 中使用新引号的問題嗎? 我們可以讓 m4 繼續執行 c (continue) 指令,然後嘗試最初出現問題的示例:

(hexagon-gdb) c
Continuing.
define(baz,defn(<QUOTE>foo<UNQUOTE>))

baz
0000
           

成功! 新報價現在與預設報價一樣有效。 問題似乎隻是定義錯誤長度的兩個拼寫錯誤。 我們通過給它一個 EOF 作為輸入來允許 m4 退出:

Ctrl-d
Program exited normally.
           

調試器生成的消息“程式正常退出”。 表示 m4 已經執行完畢。 我們可以使用 quit 指令結束我們的調試會話。

(hexagon-gdb) quit
           

繼續閱讀