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