emacs
源码分析(五)因为emacs
的C
源码中有大量的宏,在gdb
中调试是非常痛苦的,所以有下面的内容:
emacs
源码的方式就像在“emacs
源码分析(四)”中提到的那样,要么是定义这么复杂的宏:
(gdb) macro define sym_name(lisp_obj) XSTRING(XSYMBOL(lisp_obj).u.s.name).u.s.data
(gdb) p sym_name(0xdd70)
$9 = (unsigned char *) 0x100a6c4c3 <o_fwd+15843> "top-level"
要么就是写下这么一大段gdb
命令:
(gdb) p XTYPE(XCONS(XCONS(Vtop_level).u.s.u.cdr).u.s.car)
$20 = Lisp_String
(gdb) p XSTRING(XCONS(XCONS(Vtop_level).u.s.u.cdr).u.s.car).u.s.data
$21 = (unsigned char *) 0xa000dfe08 "loadup.el"
不经意间我发现了emacs
提供了调试帮助文件,见etc/DEBUG
。这很有帮助,以下内容大部分来自该文件。
emacs
中使用M-x gdb RET
启动gdb
,这个方式我没有采用,因为我经常使用的bash
里快速切换历史命令的C-n
和C-p
快捷键,但在emacs
里变成了上下移动光标。src
目录中的.gdbinit
文件加载进来,里面有大量的自定义的调试命令,用这个方式加载:(gdb) source ./src/.gdbinit
(gdb) break foo.c:1234 if PT >= 9876
当出错时想要查看堆栈,在哪个函数处下断点呢?答:Fsignal
。
只要加载了src/.gdbinit
文件后就有了pp
命令,就可以替换“emacs
源码分析(四)”中提到的p XSTRING(XCONS(XCONS(Vtop_level).u.s.u.cdr).u.s.car).u.s.data
了,这下打印Vtop_level
变量就很方便了,只需要:
(gdb) pp Vtop_level
(load "loadup.el")
pp
命令,还有很多,比如我用过的pr
,xtype
,pv
,xstring
,xsymbol
等等。xtype
命令需要说明一下,如果没有运行过gdb
的p
命令而直接运行xtype
,则该命令不会有任何输出,如图: