gdb系列之一 一个GDB会话样例




翻译:shyboysby.spaces.live.com

本翻译遵从GPL。参见:
gdb is free software, protected by the gnu General Public License (GPL). The GPL gives
you the freedom to copy or adapt a licensed program—but every person getting a copy also
gets with it the freedom to modify that copy (which means that they must get access to the
source code), and the freedom to distribute further copies. Typical software companies use
copyrights to limit your freedoms; the Free Software Foundation uses the GPL to preserve
these freedoms.
Fundamentally, the General Public License is a license which says that you have these
freedoms and that you cannot take these freedoms away from anyone else.
欢迎转载(请注明出处),但不允许用以商业赢利。本翻译保留相应权利。
自由软件需要自由文档。
自由属于人民。

GDB:第一章
第一章:一个GDB会话样例
1 一个GDB会话样例
  你可以随意用这部手册来了解有关GDB的一切。然而,一些趁手的命令就足以开始使用调试器。这一章介绍了这些命令。
  在这个简单的会话里,我们强调用户输入用黑体来显示,这样可以和环境输出明确的区分开来。
  GNU m4(通用宏处理器)的以前版本有以下的一个bug:有时候,在我们改变了宏默认的引号字符串的时候,用来在别的宏里捕获
宏定义的命令就失效了。在接下来简短的m4例子里,我们定义了一个展开是“0000”的宏foo;我们接着用m4内建的defn来定义宏bar,bar的
值也是“0000”。然而,在我们用<QUOTE>来替代开引号字符和用<UNQUOTE>替代闭引号字符的后,定义一个同义词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来看看发生了什么。
$ 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 6.8.50.20080307, Copyright 1999 Free Software Foundation, Inc…
(gdb)
  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 命令,m4就在GDB的控制下运行了。只要还没有运行到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接着运行当前函数的下一行指令。
(gdb) n
882 set_quotes((argc >= 2) ? TOKEN_DATA_TEXT(argv[1])
: nil,
  set_quotes看上去像有可能失败的子函数。为了进入子函数,我们可以用命令s(step)而不是用next。step进入被调用的
子函数的第一行,所以step进入set_qoutes.
(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

我们step几行来观察会发生什么。在开始的两次为了避免进入xstrdup子程序,我们用’s‘;接下来的两次我们用’n’。
(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);
  最后一行输出看上去有点怪异;我们可以检查变量lquote和rquote的值来看看它们是否是真的是我们所期待的新的
左右引号。我们用命令p(print)
(gdb) p lquote
$1 = 0x35d40 “<QUOTE>”
(gdb) p rquote
$2 = 0x35d50 “<UNQUOTE>”
lquote和rquote确实是新的左右引号。为了查看一些相关的信息,我们可以用命令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
让我们step两行(设置len_lquote和len_rquote),然后检查这两个变量的值。
(gdb) n
539 len_rquote = strlen(lquote);
(gdb) n
540 }
(gdb) p len lquote
$3 = 9
(gdb) p len rquote
$4 = 7
假设len_lqoute和len_rquote分别代表lqoute和rquote的长度,很显然这个结果是错误的,我们可以用命令p来设置
较合理的值,p命令不仅可以打印表达式的值,而且表达式也可以调用子函数,也可以给表达式赋值。
(gdb) p len lquote=strlen(lquote)
$5 = 7
(gdb) p len rquote=strlen(rquote)
$6 = 9
是不是这样就足以修正m4内建的defn关于使用新的引号的错误了呢?我们可以用命令c让m4继续执行,接着试这个刚刚过引起问题的例子:
(gdb) c
Continuing.
define(baz,defn(<QUOTE>foo<UNQUOTE>))
baz
0000
成功了!这个新的引用现在和默认的一样正确了。这个问题看来是两个形参搞错了。我们输入一个EOF让m4退出:
Ctrl-d
Program exited normally.
消息’Program exited normally.’是GDB输出的;它显示了m4已经执行完了。我们可以用quit命令来结束GDB会话。


转载   http://zhiwei.li/text/2010/01/gdb%e6%89%8b%e5%86%8c1%e4%b8%80%e4%b8%aagdb%e4%bc%9a%e8%af%9d%e6%a0%b7%e4%be%8b/

如有版权问题,请联系QQ  858668791

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。