使用gdb debug libvirt 心得

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/yadehuiyin/article/details/80799267

最近开始阅读libvirt源码,并且使用gdb跟踪源码运行,在此记录:

1. libvirt 源码下载和解压:

wget http://libvirt.org/sources/libvirt-1.2.7.tar.gz
tar -xf libvirt-4.0.0.tar.xz

所有的源文件放在 libvirt-4.0.0/source 下

2. 编译和运行libvirt, 注意编译的时候要加上--enable-debug=yes 参考文章(未写)

3. 查看libvirt运行,并用gdb监控libvirtd

]# ps aux|grep libvirtd
root     18320  9.3  0.0 796864 29184 ?        Ssl  11:20   0:00 /usr/sbin/libvirtd
root     18424  0.0  0.0 110528  2496 pts/1    S+   11:20   0:00 grep --color=auto libvirtd
]# gdb libvirtd  18320
GNU gdb (GDB) Red Hat Enterprise Linux 7.12.1-48.el7
......
0x0000ffffa1a90f8c in poll () from /lib64/libc.so.6
(gdb) 

接下来就可以进行debug了。

gdb 的功能还是很强大的,具体使用网络上有很多教程,这里附上一个我觉得写的最好的,http://www.unknownroad.com/rtfm/gdbtut/

里面有关于watchpoint , breakpoint 和gdb的相关使用技巧等,这里就不复述了,用空的话将来可以把这个文章翻译过来。

4. debug实例

这里给出一个例子,为了追踪 “virsh domhostname”查询无法获得虚拟机hostname的原因。

]# virsh domhostname centos
error: failed to get hostname
error: this function is not supported by the connection driver: virDomainGetHostname

会出现virDomainGetHostname 无法支持,但是具体不支持的原因没有在log文件中显示,在gdb中设置断点

(gdb) break virDomainGetHostname
Breakpoint 1 at 0xffffa20784d0: file libvirt-domain.c, line 10880.
(gdb) 
再在另外一个terminal中输入virsh domhostname centos, 这时候不会有任何输出,需要在gdb中让libvirt继续运行。回到gdb所在terminal中,让libvirt继续运行,当运行到方法virDomainGetHostname时,运行会中断
(gdb) c
Continuing.
[Switching to Thread 0xffff98bdf100 (LWP 18328)]
Thread 6 "libvirtd" hit Breakpoint 1, virDomainGetHostname (domain=domain@entry=0xffff60000930, flags=0) at libvirt-domain.c:10880
10880   {
(gdb)

继续调用逐行调试,并且查看变量变化,跟踪到导致错误的变量。

(gdb) n
10883       VIR_DOMAIN_DEBUG(domain, "flags=0x%x", flags);
......
(gdb) n
10890       if (conn->driver->domainGetHostname) {
(gdb) n
10898       virReportUnsupportedError();
(gdb) 

这里触发了virReportUnsupportedError()的错误,查看conn->driver->domainGetHostname的值 

(gdb) print *conn->driver->domainGetHostname
Cannot access memory at address 0x0

这个函数指针还保持在初始化状态。继续输出conn->driver的值,了解到这里调用的是qemu_driver.

(gdb) print *conn->driver
$4 = {name = 0xffff82544ab0 "QEMU"

回到代码中,发现domainGetHostname这个方法指针只在remote_driver.c 和openvc_driver.c中有初始化

Openvz_driver.c (openvz):    .domainGetHostname = openvzDomainGetHostname, /* 0.10.0 */

Remote_driver.c (remote):    .domainGetHostname = remoteDomainGetHostname, /* 0.10.0 */

没有在qemu_driver.c中定义,所以这个方法不支持用qemu启动的虚拟机。

注意:

需要修改libvirtd.conf中keepalive的值,默认时间只有5秒,很容易出现

error: Disconnected from qemu:///system due to keepalive timeout

在运行virsh命令的时候可以添加-k0,让命令一直保持keep alive,但是还是会出现链接断开的情况

e.g.  virsh -k0 domfsinfo test_vm

总结:

使用gdb来逐步跟踪命令行运行输出变量的值,使得阅读Libvirt源码变得轻松了很多,尤其是结合sourceisight, 让其间的指针调用变得清晰。

展开阅读全文

没有更多推荐了,返回首页