Debugging with GDB v10.1中文翻译-第一章:一个GDB 会话样例

第一章:一个GDB 会话样例(未校正)

你可以在闲暇时读完这本手册来了解所有关于gdb的内容。不过,仅需几个命令就足以开始使用调试器了。本章介绍了这些命令。
在这个示例会话中,我们强调用户这样输入:input,以使它更容易从周围的输出中突出出来。
gnu m4(一个通用宏处理器)的一个初步版本表现出以下缺陷:有时,当我们改变它的缺省引用字符串时,用于在另一个宏定义中捕获一个宏定义的命令停止工作。在下面简短的m4会话中,我们定义了一个扩展到0000的宏foo然后,我们使用m4内置defnbar定义为相同的东西。但是,当我们将开始引用字符串更改为 并将结束引用字符串更改为 时,相同的过程无法定义新的同义词baz:

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

让我们来尝试看看发生了什么。

$ gdb m4
gdb is free software and you are welcome to 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.
gdb 10.1, Copyright 1999 Free Software Foundation, Inc...
(gdb)

gdb只读取足够的符号数据,以便在需要时知道在哪里可以找到剩余的符号数据;因此,第一个提示会很快出现。我们现在告诉gdb使用比通常更窄的显示宽度,这样例子就适合本手册。

(gdb) set width 70

我们需要看看m4内置的changequote是如何工作的。看了源代码之后,我们知道相关的子程序是m4_changequote,所以我们用gdb break命令在那里设置了一个断点。

(gdb) break m4 changequote
Breakpoint 1 at 0x62f4: file builtin.c, line 879.

使用run命令,我们开始在gdb控制下运行M4;只要没有运行到m4_changequote子程序,程序就照常运行:

(gdb) run
Starting program: /work/Editorial/gdb/gnu/m4/m4
define(foo,0000)

foo
0000

为了触发断点,我们调用changequote。gdb挂起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) 将程序执行到当前函数的下一行。

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

set_quotes看起来是一个很有前途的子程序。我们可以通过使用命令s(step) 而不是next来进入这个子函数。step转到任何子程序中要执行的下一行,因此它会进入set_quotes函数。

(gdb) s
set_quotes (lq=0x34c78 "<QUOTE>", rq=0x34c88 "<UNQUOTE>")
at input.c:530
530 if (lquote != def_lquote)

展示的m4现在暂停的子函数(及其参数)的显示称为堆栈帧显示。它显示了堆栈的摘要。我们可以使用backtrace命令(也可以拼写为bt),来查看我们在整个堆栈中的位置:backtrace命令为每个活动的子函数显示一个堆栈帧。

(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子函数。

(gdb) s
0x3b5c 532 if (rquote != def_rquote)
(gdb) s
0x3b80 535 lquote = (lq == nil || *lq == ’’) ? 
def_lquote : xstrdup(lq);
(gdb) n
536 rquote = (rq == nil || *rq == ’’) ? def_rquote
: xstrdup(rq);
(gdb) n
538 len_lquote = strlen(rquote);

显示的最后一行看起来有点奇怪;我们可以检查变量lquoterquote,看看它们是否是我们指定的新的左引号和右引号。我们使用命令p(print)来查看它们的值。

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

lquoterquote确实是新的左引号和右引号。为了查看一些内容,我们可以用l(list) 命令在当前行周围显示10行源代码。

(gdb) l
533 xfree(rquote);
534
535 lquote = (lq == nil || *lq == ’’) ? def_lquote
: xstrdup (lq);
536 rquote = (rq == nil || *rq == ’’) ? def_rquote
: xstrdup (rq);
537
538 len_lquote = strlen(rquote);
539 len_rquote = strlen(lquote);
540 }
541
542 void

让我们跳过设置len_lquotelen_rquote的两行,然后检查这些变量的值。

(gdb) n
539 len_rquote = strlen(lquote);
(gdb) n
540 }
(gdb) p len lquote
$3 = 9
(gdb) p len rquote
$4 = 7

假设len_lquotelen_rquote分别是lquoterquote的长度,这显然是错误的。我们可以使用p命令将它们设置为更好的值,因为它可以打印任何表达式的值——并且该表达式可以包括子函数调用和赋值。

(gdb) p len lquote=strlen(lquote)
$5 = 7
(gdb) p len rquote=strlen(rquote)
$6 = 9

这是否足以解决m4内置defn使用新引用的问题?我们可以允许m4继续使用c(continue) 命令执行,然后尝试最初导致问题的示例:

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

成功!新引用现在和默认引用一样有效。问题似乎只是定义了错误长度的两个错别字。我们允许m4退出,给它一个EOF作为输入:

Ctrl-d
Program exited normally.

消息“Program exited normally. 。来自gdb它表示m4已经完成执行。我们可以用GDB退出命令结束我们的GDB会话。

(gdb) quit
原文地址:https://www.cnblogs.com/Songhe/p/14507143.html