首先,要开启调试选项:..autogen.sh --enable-debug
开启所有模块的调试或者是 -enable-debug --enable-selective-debuginfo="sw/ xmloff/"
开启部分模块调试功能。
另外一个重要的调试选项就是 --enable-dbgutil
。此选项会增加一些 STL 的一些断言和调试代码,选项支持 GCC 平台(不包括 Mac OS X 因为 Apple 的 libstdc++ 不支持)和 MSVC 平台。
使用 --enable-debug
或者 --enable-dbgutil
选项编译所有模块大约会使用 30G 的硬盘空间,如果您想减少空间占用可以使用 --enable-selective-debuginfo
选项,或者先不使用 debug 选项编译然后在重新编译您需要调试的模块:
make <module>.clean && make <module> debug=t
有两种方法启动调试:
- 使用专用启动脚本(soffice, swriter 等)启动应用程序,然后附加应用程序进程到调试器。
- 通过应用程序直接启动 Libreoffice 进程(soffice.bin)
在以下的说明中都需要添加环境变量 $LOROOT 为您的源代码路径,也就是 autogen.sh 脚本所在的路径。
这种方法很简单, soffice 脚本会设置需要的变量。
$ instdir/program/soffice # or /sdraw /swriter ...
$ gdb --pid=$(pidof soffice.bin)
(gdb)
运行启动脚本时(soffice, swriter...),你可以加上 -norestore
选项,这样当系统发生错误时不会触发 restart/restore 恢复机制。
使用 attach <pid>
和 detach
命令附加和分离 soffice.bin 进程到 gdb。
从 3.5 版本开始,您可以通过以下简单的名利直接启动调试器:
make debugrun
从 5.0 开始这个选项也适用于 MSVC,但是只能附加到 soffice.bin
进程,。
当程序停止时,您可以查找符号、查看变量、设置断点等:
(gdb) info fun DrawEllipse
All functions matching regular expression "DrawEllipse":
File $LOROOT/svtools/source/filter.vcl/wmf/winmtf.cxx:
void WinMtfOutput::DrawEllipse(Rectangle const&);
File $LOROOT/clone/libs-gui/vcl/source/gdi/outdev5.cxx:<span style="color:#000000" />
void OutputDevice::DrawEllipse(Rectangle const&);
File $LOROOT/clone/libs-gui/vcl/source/gdi/pdfwriter.cxx:
void vcl::PDFWriter::DrawEllipse(Rectangle const&);
Non-debugging symbols:
0x00007f826dd4a318 OutputDevice::DrawEllipse(Rectangle const&)
0x00007f826dd4a318 [mailto:_ZN12OutputDevice11DrawEllipseERK9Rectangle@plt _ZN12OutputDevice11DrawEllipseERK9Rectangle@plt]
(gdb) break vcl::PDFWriter::DrawEllipse
Breakpoint 1 at 0x7f826c7c5e20: file /opt/shared/work/source_code/libreoffice/libo/clone/libs-gui/vcl/source/gdi/pdfwriter.cxx, line 159.
如上命令,已经在函数出设置了断点。设置函数断点时,必须使用函数全名,包括类名和命名空间。
设置断点的通用语法是:break <location>
,<location> 可以是函数全名、内存地址或者是文件名 + ‘:’ + 行号构成的定位。更多信息请查看 gdb 的手册: specifying a Location
用如下命令查看断点列表:
(gdb) info break
Num Type Disp Enb Address What
1 breakpoint keep y 0x00007f826c7c5e20 in vcl::PDFWriter::DrawEllipse(Rectangle const&)
at /opt/shared/work/source_code/libreoffice/libo/clone/libsgui/vcl/source/gdi/pdfwriter.cxx:159
用如下命令删除断点:
clear <location>
delete <breakpoint number>
当您设置的断点符号未加载时,您可以设置 pending breakpoint,当符号可用时 gdb 会自动进入断点。
(gdb) break SVGActionWriter::ImplWriteRect
Can't find member of namespace, class, struct, or union named "SVGActionWriter::ImplWriteRect"
Hint: try 'SVGActionWriter::ImplWriteRect<TAB> or 'SVGActionWriter::ImplWriteRect<ESC-?>
(Note leading single quote.)
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 1 (SVGActionWriter::ImplWriteRect) pending.
(gdb) info break
Num Type Disp Enb Address What
1 breakpoint keep y <PENDING> SVGActionWriter::ImplWriteRect
通过如下命令设置 pending breakpoint:
set breakpoint pending on
恢复默认使用 "auto" 选项。
关于 pending breakpoint 的讨论:您必须记住函数全名 info fun
命令是无效的,因为符号没有加载。一个可行的解决方案是使用 shared objet events(译者注:详情查看下文)
在 gdb 7 及以后的版本中,通过 gdb pretty pringters 您可以打印 UTF-16 的 rtl::OUString 和 8-bit 的 rtl::OString 的内容。同时也可以其他对象的格式化内容,如: Sequence, Date, Time 等等。如果你不需要显示格式化内容请使用 print/r(或者 p/r)。 pretty printers 在 gdb 启动时自动激活。
备注 1:如果您的 pretty printers 没有正常工作,可能是因为权限设置导致的,请认真查看日志信息,如果是请尝试在 $HOME/.gdinit
中加入:
add-auto-load-safe-path /path/to/your/lo/git
备注 2:Apple gdb 不支持 Pyton pretty-printers。
pretty-print 同样可以格式化打印出 STL 容器的内容。
如果您使用早期版本的 LO pretty printer 没有正常工作是因为 LO 使用自己的 libstdc++,所以 gdb 不鞥自动加载相关的 Python 脚本。
在 Fedora 16 系统中,您可以在 .gdbinit
文件中加入(您可能需要根据您的系统修改相应的版本号):
# workaround OOo/LO shipping its own libstdc++
python
import sys
sys.path.insert(0, '/usr/share/gcc-4.6.1/python')
end
source /usr/share/gdb/auto-load/usr/lib64/libstdc++.so.6.0.16-gdb.py
当一个共享库加载时引发共享对象事件。默认情况下共享对象事件是关闭的,你可以使用如下命令开启共享对象事件:
set stop-on-solib-events 1
开启共享事件对象后,每次加载共享库是 gdb 会暂停,您可以查找符号设置断点等。
您可能只需要找到你需要的共享库加载,这个过程中您需要多次执行 continue 命令。
那么,是如何找您想要的共享库呢,您可以使用 info shared <reg expr>
命令,此命令会使用正则表达式匹配出所有符合条件的共享库。
如果您想查看 UNO reference 指向的真是 C++ 对象,您可以使用如下命令:
(gdb) print *rShape._pInterface
$1 = {_vptr.XInterface = 0x2aaac99f9728 <vtable for SvxShapeText+648>}
(gdb) print rShape._pInterface
$2 = (com::sun::star::uno::XInterface *) 0x2313e9
一些 gdb 的其他帮助信息:
-
info mutex: 显示有获取 mutex 的线程。
-
fcatch: stop when an exception is thrown, but only if a certain given function is on the stack.
待翻译...