目标:配置环境实现linux内核的双机调试(调试机器host,被调试机器target)
步骤:
- 确认内核有内核调试支持(一般都有)
- 符号文件:
- target:下载安装自己系统内核版本的符号文件(仅调试可能不必要)
- host:安装target对应内核版本的符号文件以备调试
- 源代码:
- target:下载本机内核源码压缩包,解压放在/usr/src目录下(仅调试可能不必要)
- host: 在指定路径放上target内核的源代码以备调试(等调试知道路径后再做)
- 串口通信
- 修改target启动程序
- 配置host
- 调试及善后
内核调试支持
首先,如果对于从Ubuntu官网下载安装包而安装的系统,不需要重新编译内核。因为,Canonical(开发Ubuntu的公司)在编译时,已经开启了内核调试支持。如果想确认一下,可以查看/boot目录下的编译选项文件,比如Ubuntu 16.04 LTS版本:
1 | :/boot$ cat config-4.8.0-36-generic | grep -i "GDB" |
可以看到,关于KDB和KGDB的几个选项都是开启的(yes)。
如果内核不支持,请移步这里。
本文实验环境如下:
Windows 10 ,VMware® Workstation 12 Pro 下开两个虚拟机
target:Linux ubuntu 4.8.0-36-generic #36~16.04.1-Ubuntu SMP
host: Linux ubuntu 4.13.0-43-generic #48~16.04.1-Ubuntu SMP
使用 uname -a 查询系统版本信息。
符号文件
准备:target内核版本符号文件
源代码
打开/etc/apt/sources.list,启用deb-src,sudo apt-get update更新
1 | vim /etc/apt/sources.list |
搜索所有版本的source code:apt-cache search linux-source
安装指定版本的source code:sudo apt-get install linux-source-x.x.x
解压缩得到源码 :sudo tar -xvf linux-source-4.8.0.tar.bz2 (host中安放源码的路径需要调试后才知道,见7.3)
串口通信
建立host与target之间的串口连接。
虚拟机设置中移除打印机,添加串口,target为服务器,host为客户端。详见此链接《移除打印机,添加串口》一节。
修改target启动程序
需要让target在开机时候可选择进入kgdb的调试状态,首先需要修改grub文件,增加grub引导时候的菜单项。
sudo vim /etc/grub.d/40_custom
从/boot/grub/grub.cfg中复制一个菜单项(menuentry)过来,最好选正常启动的一项,
修改项名便于识别,倒数第三句增加KGDB选项:
kgdbwait kgdb8250=io,03f8,ttyS0,115200,4 kgdboc=ttyS0,115200 kgdbcon nokaslr
修改完的40_custom文件样板如:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24#!/bin/sh
exec tail -n +3 $0
# This file provides an easy way to add custom menu entries. Simply type the
# menu entries you want to add after this comment. Be careful not to change
# the 'exec tail' line above.
menuentry 'Ubuntu, kgdb, with Linux 4.8.0-36-generic' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-4.8.0-36-generic-advanced-aeac2f22-dfde-4e98-9c78-bb46f5724517' {
recordfail
load_video
gfxmode $linux_gfx_mode
insmod gzio
if [ x$grub_platform = xxen ]; then insmod xzio; insmod lzopio; fi
insmod part_msdos
insmod ext2
set root='hd0,msdos1'
if [ x$feature_platform_search_hint = xy ]; then
search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 aeac2f22-dfde-4e98-9c78-bb46f5724517
else
search --no-floppy --fs-uuid --set=root aeac2f22-dfde-4e98-9c78-bb46f5724517
fi
echo 'Loading Linux 4.8.0-36-generic ...'
linux /boot/vmlinuz-4.8.0-36-generic root=UUID=aeac2f22-dfde-4e98-9c78-bb46f5724517 ro find_preseed=/preseed.cfg auto noprompt priority=critical locale=en_US quiet kgdbwait kgdb8250=io,03f8,ttyS0,115200,4 kgdboc=ttyS0,115200 kgdbcon nokaslr
echo 'Loading initial ramdisk ...'
initrd /boot/initrd.img-4.8.0-36-generic
}
修改grub的配置后,需要执行sudo update-grub来更新。更新后目标机器就准备好了。
重启按住shift,进入刚才添加的menu即可进入到被调试状态。
配置host(每次重启需要重新设置)
设置串口通信的波特率
sudo stty -F /dev/ttyS0 115200
要查看是否设置成功
sudo stty -F /dev/ttyS0
调试及善后
调试前准备
此节为在host中调试,需要target以kgdb调试状态启动,记得先配置好host端口(见6)。
编写config,用source加载(直接在gdb里输入也可)1
2set architecture i386:x86-64:intel
target remote /dev/ttyS0
开始调试
使用gdb来调试带符号的vmlinux
1 | sudo gdb /usr/lib/debug/boot/vmlinux-4.8.0-36-generic |
善后:在host中安放target源码(接3)
(gdb) l
查找源码。本来应该显示具体的源码,但是这里只是打印出了所在文件,这是因为在这个路径下没有源码。
所以说我们就建立这个路径,然后把源码放进去:
创建路径/build/linux-hwe-eyfT8D/linux-hwe-4.8.0,将源码解压到这里
然后dir设置好目录
dir /build/linux-hwe-edge-gyUj63/linux-hwe-edge-4.10.0
单步调试
详见此链接《单步调试》。
Tips:target运行1
sudo su && echo g > "/proc/sysrq-trigger"
进入假死,方便host下断点
参考链接
[1] : 清楚,双机环境相同 https://www.anquanke.com/post/id/105342#h2-0
[2] : 全面 http://advdbg.org/blogs/advdbg_system/articles/7147.aspx