分类: LINUX
前言:
经过多天的努力尝试,不知道死了多少次机器重装了多少次系统,终于将KGDB环境搭建好。过程也分享一下。
一、准备环境
目标机:也就是target,调试内核机,是一台装有ubuntu系统的linux机器。
主机:即Host,采用虚拟机ubuntu环境。
两台机器需要用串口线连接。
二、编译内核
因为我的目标机现在的内核是没有开启KGDB调试的,所以需要重新编译内核。
1.下载源代码
从网站 https://www.kernel.org/ 下载源代码linux-3.12.1,拷贝到/usr/work/目录下。
2.解压
进入到源码目录/usr/work,进行解压:tar -zxvf linux-3.12.1.tar.gz
3.配置内核选项
进入源码目录,执行make menuconfig进行KGDB的内核选项配置。
因为是较新的内核,所以网上说的一些选项都不存在了,例如:Prompt for development and/or incomplete code/drivers已不存在该选项。
//建议打开的选项
(1)CONFIG_DEBUG_INFO = y 该选项可以使得编译的内核包含一些调试信息,使得调试更容易。
位置:---->Kernel hacking
---->Compile-time checks and compiler options
---->Compile the kernel with debug info
(2)CONFIG_FRAME_POINTER = y 该选项将使得内核使用帧指针寄存器来维护堆栈,从而就可以正确地执行堆栈回溯,即函数调用栈信息。
位置:---->Kernel hacking
---->Compile-time checks and compiler options
---->Compile the kernel with frame pointers
(3)CONFIG_MAGIC_SYSRQ = y (如果你选择了KGDB_SERIAL_CONSOLE,这个选项将自动被选上) 激活"魔术 SysRq"键. 该选项对kgdboc调试非常有用,kgdb向其注册了‘g’魔术键来激活kgdb 。
位置:---->Kernel hacking
---->Magic SysRq key
当你想手动激活kgdb时,你可以触发SysRq的g键, 如:
$ echo"g">/proc/sysrq-trigger
//建议关闭的选项
(4)CONFIG_DEBUG_RODATA = n 该选项是将内核的一些内存区域空间设置为只读,这样可能导致kgdb的设置软断点功能失效。所以推荐将该选项关闭。
位置:---->Kernel hacking
---->Write protect kernel read-only data structures
(5)CONFIG_DEBUG_SET_MODULE_RONX =n,该选项会将内核模块空间设置为只读,这样会导致调试内核模块时设置断点功能失效,设置断点时出现以下错误,(调试内核模块时吃过亏又重新编译的内核)所以将其关闭。
Cannot insert breakpoint 1.
Error accessing memory address 0xf90f6000: Unknown error -1.
位置:---->Kernel hacking
---->Set loadable kernel module data as NX and test as RO.
//必须使能的选项
(5)CONFIG_KGDB = y
位置:---->Kernel hacking
---->KGDB: kernel debugger
(6)CONFIG_KGDB_SERIAL_CONSOLE = y 使KGDB使用串口进行通信。
位置:---->Kernel hacking
---->KGDB: kernel debugger
---->KGDB: use kgdb over the serial console
(7)其余:
在Kernel hacking-->KGDB: kernel debugger目录下,除了KGDB:internal test suite外的选项全部使能y。
4.编译内核
make
5.安装内核模块
make modules_install
模块被安装到 /lib/modules/3.12.1 目录下。
6.安装内核二进制映象文件
make install
(1)在此过程中,会在/boot目录下生成config-3.12.1 文件,自动生成根文件系统initrd.img-3.12.1 文件,内核映像文件vmlinuz-3.12.1 文件,以及符号表System.map-3.12.1 文件。
(2)并且会自动修改grub.cfg文件,在该文件中自动添加3.12.1 内核的启动选项。
(3)注意原来旧内核boot目录下的文件不要删掉,以防新内核启动不了。
(4)自动修改的grub.cfg文件添加内容如下所示:
menuentry 'Ubuntu-KGDB' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-simple-42043581-474f-47bd-9bde-93e0de01a1ec' {
recordfail
gfxmode $linux_gfx_mode
insmod gzio
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 42043581-474f-47bd-9bde-93e0de01a1ec
else
search --no-floppy --fs-uuid --set=root 42043581-474f-47bd-9bde-93e0de01a1ec
fi
linux /boot/vmlinuz-3.12.1 root=UUID=42043581-474f-47bd-9bde-93e0de01a1ec ro quiet splash $vt_handoff
initrd /boot/initrd.img-3.12.1
}
7.重新启动系统
重启后,uname -a查看启动新内核,内核编译升级成功,此时的内核是支持KGDB调试的。
如果系统启动不起来很可能是生成根文件系统那一步出错,回去重新查看确保生成initrd.img-3.12.1没有错误。
三、进行KDGB连接
1.目标机grub.cfg修改,添加kgdbwait kgdboc=0,9600,如下所示:
menuentry 'Ubuntu-KGDB' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-simple-42043581-474f-47bd-9bde-93e0de01a1ec' {
recordfail
gfxmode $linux_gfx_mode
insmod gzio
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 42043581-474f-47bd-9bde-93e0de01a1ec
else
search --no-floppy --fs-uuid --set=root 42043581-474f-47bd-9bde-93e0de01a1ec
fi
linux /boot/vmlinuz-3.12.1 root=UUID=42043581-474f-47bd-9bde-93e0de01a1ec ro quiet splash $vt_handoff kgdbwait kgdboc=0,9600
initrd /boot/initrd.img-3.12.1
}
(1)kgdboc=0,9600 :kgdboc 的意思是 kgdb over console,这里将kgdb连接的console设置为ttyS0,波特率为9600,如果不在内核启动项中配置该参数,可以在进入系统后执行命令:
echo ttyS0 > /sys/module/kgdboc/parameters/kgdboc
(2)kgdbwait:使 kernel 在启动过程中等待 gdb 的连接。
(3)然后重启target,系统就会暂停在kgdbwait处,等待host端的gdb连接。
2.主机Host端
(1)将在target端编译的内核源码全部拷贝到Host的/usr/src目录下,然后进入编译后linux源代码根目录。执行下面命令:
[root]#gdb vmlinux //装入未压缩的内核映像
(gdb) set remotebaud 9600 //设置串口速率
(gdb) target remote /dev/ttyS0 //连接串口1
Remote debugging using /dev/ttyS0
kgdb_breakpoint () at kernel/kgdb.c:1721
1721 wmb(); /* Sync point after breakpoint */
warning: shared library handler failed to enable breakpoint
(gdb) c
Continuing. //继续执行,Server就继续下面的系统初始化了.
//系统启动完成后的内核调试:如果想再中断,则要在目标机上输入,系统同样会中断,进入假死状态,等待远程gdb的连接
[root]# echo g > /proc/sysrq-trigger
SysRq : DEBUG
(2)注意:
一开始host连不上target,原因是因为我的机器在115200波特率下两台机器不能相互通信,但是能在9600下通信,所以我把通信频率改为9600,就能连接上target端的KGDB,就能进行调试了。所以在连接前,首先要确定你的两台机器在你设置的波特率下要能通信。
四、其他参考信息
1.ubuntu10.10下改变默认启动的操作系统
sudo gedit /boot/grub/grub.cfg
打开grub.cfg 这个文件,将文件中的 set default="0" 中的 0 改成对应欲默认启动的操作系统的序号(从0开始) ,然后保存。其中menuentry列出了启动时所有可选的内核菜单
2.Ubuntu12.04 安装软件apt-get install都提示:Unable to locate package错误,解决方法非常简单,终端输入以下命令即可:sudo apt-get update
sudo apt-get update究其原因,应该是刚安装,软件源还来不及更新,所以才会无法找到包。