GDB调试CentOS内核

通过GDB和QEMU调试Linux内核已经有很多介绍了,但基本都是制作简单的根文件系统。有时候需要调试的模块或者场景需要用到发行版的Linux,因此本文介绍调试CentOS内核的步骤。

GDB调试Linux内核关键步骤

debug_kernel.jpg
  1. 首先需要有一个可以启动运行Cent OS 7的虚拟机
    • 准备一个qcow2格式的磁盘镜像文件centos.img.qcow2,通过CentOS的光盘iso将系统安装到这个磁盘镜像中。
  2. 虚拟机需要连接外部网络(例如mount nfs文件系统、调试内核的网络代码等),所以我们要为QEMU虚拟机选择合适的网络方案
    • 通过将tap和物理网卡加入到bridge
  3. GDB的调试需要源代码和编译生成的原始文件vmlinux,因此我们要下载Linux内核源代码,完成patch、configure和编译等工作;
  4. 编译Linux内核的最终产品为bzImage,因此要能够更新虚拟机中的内核bzImage以及GRUB配置;
  5. QEMU内置一个gdbserver,通过”-s -S”选项来开启并等待GDB的连接,默认端口为1234
    • -S freeze CPU at startup (use 'c' to start execution)
    • -s shorthand for -gdb tcp::1234
    • 也可以在QEMU命令行中通过gdbserver tcp::1234来指定gdbserver的端口号

安装CentOS 7.1到虚拟磁盘

从CentOS网站上下载CentOS 7的安装包CentOS-7-x86_64-DVD-1503-01.iso

qemu-img create centos.img.qcow2 -f qcow2 40G

qemu-system-x86_64 -cdrom CentOS-7-x86_64-DVD-1503-01.iso -hda centos.img.qcow2 -boot d -net nic -net user -m 4096 -vnc 0.0.0.0:1 -enable-kvm -smp 2
  • 通过VNC View连接ip:5901进入虚拟机的控制台,在控制台中完成CentOS 7.1的安装过程
  • 安装完成后得到虚拟机的磁盘镜像centos.img.qcow2
  • 重新启动QEMU虚拟机:
qemu-system-x86_64 -m 4096 -vnc 0.0.0.0:1 centos.img.qcow2

通过VNC Viewer连接到虚拟机的控制台,确认CentOS 7正常启动

VNC

QEMU虚拟机网络配置

QEMU支持多种方式的网络配置,对于需要访问外部网络的虚拟机,最合适的方式是tap桥接模式,即将虚拟机网卡对应的tap网卡和Host的物理网卡加入到同一个bridge中

  • 创建bridge并将物理网卡加入到该bridge中
/home/gj/virt/qemu-kernel/net_config.sh
#!/bin/sh
ifconfig enp2s0 0.0.0.0
brctl addbr br0
brctl addif br0 enp2s0
dhclient br0
  • QEMU创建虚拟机时指定-net nic -net tap,script=/etc/qemu-ifup1,其中qemu-ifup1由QEMU初始化虚拟机网卡时调用,它负责将tap网卡加入到bridge中
/etc/qemu-ifup1
#! /bin/sh
# TAP interface will be passed in $1
ifconfig $1 up
brctl addif br0 $1

虚拟机启动之后可以看到其已经通过DHCP的方式自动获取到ip

编译Linux内核源代码

下载Linux内核的源代码可以在Linux内核网站上下载“干净”的版本,但是需要自己来配置内核,更简单的办法是在CentOS网站上下载对应版本的rpm源码包,这样不需要关心patch和内核配置,比如CentOS 7.1对应的源码包kernel-3.10.0-229.1.2.el7.src.rpm

  • 安装源码包
rpm –ivh kernel-3.10.0-229.1.2.el7.src.rpm
  • 通过rpmbuild -bp完成源码的patch和config工作(-bp表示prepare)
rpmbuild -bp ~/rpmbuild/SPECS/kernel.spec

完成之后我们就得到了一套准备好的待编译的源代码,此时完全可以将这一套源代码打包拷贝到别处重复使用。rpmbuild -bb可以完成代码的prepare和编译打包的全部工作,直接生成新内核的rpm安装包。

  • 进入Linux内核源码目录
cd ~/rpmbuild/BUILD/kernel-3.10.0-229.1.2.el7/linux-3.10.0-229.1.2.el7.centos.x86_64/
make bzImage && make modules

生成gdb需要的vmlinux和待安装的新内核bzImage(arch/x86_64/boot/bzImage)

安装新内核

编译完成需要将生成的内核(bzImage)和modules安装到虚拟机中去,一种方式是制作rpm包然后拷贝到虚拟机中去安装:

make binrpm-pkg INSTALL_MOD_STRIP=1

另外一种方式:在host中将内核源码通过nfs共享给虚拟机,由虚拟机自己来完成install的工作

  1. 进入源码目录,修改代码后编译
cd ~/rpmbuild/BUILD/kernel-3.10.0-229.1.2.el7/linux-3.10.0-229.1.2.el7.centos.x86_64
make bzImage
make modules (第一次编译安装新内核时需要)
  1. QEMU启动虚拟机
qemu-system-x86_64 -m 4096 -vnc 0.0.0.0:1 centos.img.qcow2 -net nic -net tap,script=/etc/qemu-ifup1 -enable-kvm -smp 2

*注意此时不需要’-s -S’选项,同时可以新增’-enable-kvm’和’-smp 2’来提高虚拟机的性能;

  1. 在虚拟机中mount Host导出的源码目录
showmount -e 192.168.10.115
Export list for 192.168.10.115:
/root/rpmbuild/BUILD 192.168.10.0/24
mount -t nfs 192.168.10.115:/root/rpmbuild/BUILD /mnt/nfs/
  1. 进入源码目录安装新编译的内核
make modules_install INSTALL_MOD_STRIP=1    (第一次编译安装新内核时需要)
make install

安装成功后重启虚拟机后通过uname -a确认内核更新成功

开始调试内核

  1. 检查网络配置
  2. 在会话1中通过QEMU创建虚拟机
cd /home/gj/virt/qemu-kernel
qemu-system-x86_64 -m 4096 -vnc 0.0.0.0:1 centos.img.qcow2 -net nic -net tap,script=/etc/qemu-ifup1 -s -S

使用VNC viewer连接ip:5901

  1. 会话2中进入源码目录并gdb
cd ~/rpmbuild/BUILD/kernel-3.10.0-229.1.2.el7/linux-3.10.0-229.1.2.el7.centos.x86_64
gdb vmlinux
  1. 在gdb中连接QEMU的gdbserver并设置断点
(gdb) target remote localhost:1234
Remote debugging using localhost:1234
0x0000000000000000 in irq_stack_union ()
(gdb) break yfs_mount
Breakpoint 1 at 0xffffffff812b259f: file fs/yfs/super.c, line 777.
(gdb) c
Continuing.

此时通过VNC Viewer连接到虚拟机的控制台,应该可以看到启动的输出

  1. 在虚拟机中执行调试代码的操作,然后会话2中会被break住,此时像普通程序一样进行gdb调试;

附一:gdb编译

GDB在调试64位Linux内核时会出错:

Remote ‘g’ packet reply is too long

解决办法是下载GDB的源代码,如下所示修改remote.c

if (buf_len > 2 * rsa->sizeof_g_packet)
    error (_("Remote 'g' packet reply is too long: %s"), rs->buf);

修改为:

if (buf_len > 2 * rsa->sizeof_g_packet) {
//error (_("Remote 'g' packet reply is too long: %s"), rs->buf);
    rsa->sizeof_g_packet = buf_len ;
    for (i = 0; i < gdbarch_num_regs (gdbarch); i++) {
        if (rsa->regs->pnum == -1)
            continue;
        if (rsa->regs->offset >= rsa->sizeof_g_packet)
            rsa->regs->in_g_packet = 0;
        else
            rsa->regs->in_g_packet = 1;
    } 
}

重新编译并安装GDB

./configure
make && make install

附二:qemu编译

Redhat/CentOS不推荐直接使用qemu-kvm,而是需要通过libvirt的接口来创建虚拟机,因此要使用QEMU推荐下载QEMU源代码编译安装,编译安装也很简单:

./configure --target-list=x86_64-softmmu
make && make install

附三:虚拟机组网

桥接

上文介绍中QEMU虚拟机是通过桥接方式连接外部网络,其将虚拟机对应的tap网卡和物理网卡加入到同一个bridge中,将物理网卡的ip分配到bridge上,这样从逻辑上看虚拟机的报文都是通过bridge进出

Bridge

桥接方式的好处是每个VM都可以获取到物理机同网段的ip,因此也可以访问物理机所属的网络

NAT

有时虚拟机不需要访问物理机所属的网络(比如受ip冲突影响),虚拟机只需要能够互相访问同时可以访问外网,这时NAT方式是比较适合的。其将所有VM对应的tap网卡加入到同一个bridge中,这个bridge作为这个私有网段的网关,每个VM启动后配置一个同网段的ip;然后物理网卡为这个bridge做NAT。

NAT

配置方式如下:

  1. Host网络初始化脚本
#!/bin/sh
# create bridge
brctl addbr br0-qemu 
ifconfig br0-qemu 192.168.125.1
iptables -t nat -A POSTROUTING -o enp2s0 -j MASQUERADE
iptables -A FORWARD -i enp2s0 -o br0-qemu -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i br0-qemu -o enp2s0 -j ACCEPT

echo 1 > /proc/sys/net/ipv4/ip_forward
  1. qemu初始化脚本 /etc/qemu-ifup-nat
#! /bin/sh
# TAP interface will be passed in $1
ifconfig $1 promisc up
brctl addif br0 $1

上述方式中所有VM的ip, gateway和DNS都需要配置成固定的。如果要实现VM自动分配私有ip那么还需要在host上安装一个本地的DHCP Server

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容