分享好友 系统运维首页 频道列表

【强转】QEMU+GDB调试linux内核全过程

Linux系统  2023-03-08 15:030

昨天更新了一篇名为《QEMU+GDB调试linux内核全过程》[link][https://blog.csdn.net/weixin_37867857/article/details/88138432]的博客,发现排版比较混乱,而且思维也比较混乱。咋一看下来简直是惨不忍睹,而且会给读者在安装过程中一种云里雾里的感觉,加上将近一个半月没有更新博客,导致对于博客的写作比较生疏了。所以决定重新更新一篇博客,以弥补昨天的遗憾。
为了更新本博客,于今天特意安装了一款虚拟机,重头开始指导并且总结怎么调试linux内核,不足之处敬请大家谅解。

1.需要下载的工具或者源码

使用qemu+gdb调试linux内核需要下载以下源码包或者软件包:

	1. ubuntu14.04;
	2. qemu;  
	3. linux内核,  版本2.6.32.20
	4. gcc,  版本4.4
	5. gdb, 版本7.9  
	6. busybox, 版本1.25.0
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

下面先解释一下各个软件的作用:

1. 综述

1.1 ubuntu14.04

是我们需要编译Linux内核和各个调试软件运行的操作系统,建议虚拟机安装即可,物理机太浪费;虚拟机安装方法网上教程比较多,不在一一赘述。

1.2 qemu

是我们在虚拟机里面运行编译好的内核的镜像的一种方式,具体使用方法见以下使用。

1.3 linux内核

是我们主要调试的代码,安装gcc是为了编译linux内核,请注意,我们如果想在qemu里面调试特定版本的内核代码,一定要编译,编译好的镜像才有可能使用(为什么说有可能?是因为不稳定的内核代码有可能会产生panic)。

1.4 gdb

这个是我们主要的调试工具。

1.5 gcc

这个是我们主要的linux内核代码编译工具。

1.6 busybox

这个需要重点说明一下,是制作我们根文件系统的主要工具。什么是跟文件系统?
根文件系统首先是内核启动时所mount的第一个文件系统,内核代码映像文件保存在根文件系统中,而系统引导启动程序会在根文件系统挂载之后从中把一些基本的初始化脚本和服务等加载到内存中去运行。

2. 工具及源码下载

ubuntu14.04桌面版下载不需要赘述。网上很多。

2.1 qemu下载

sudo apt-get install qemu
  • 1

如果有提示输入密码,输入密码即可。

2.2 linux内核

内核下载网址为:
[link][https://mirrors.edge.kernel.org/pub/linux/kernel/v2.6/]
或者使用终端命令:

wget https://mirrors.edge.kernel.org/pub/linux/kernel/v2.6/linux-2.6.32.20.tar.gz
  • 1

2.3 gcc下载

由于ubuntu14.04默认安装gcc为4.8的版本,对于编译2.6.32.20的内核有点高,所以需要下载gcc源码或者更换gcc版本。

对于gcc的版本查看使用如下命令: 
  • 1
alex@ubuntu:~$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper
...此处省略
gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

对于特定版本的gcc的安装如下:

sudo apt-get install gcc-4.4
ls /usr/bin -l | grep gcc #可以看到gcc是一个链接文件,连接到gcc-4.8版本;可以把本链接删除,重新链接gcc到gcc-4.4版本;
sudo rm -rf /usr/bin/gcc-4.8
sudo ln /usr/bin/gcc-4.4 /usr/bin/gcc
sudo gcc -v # 查看最终链接好的版本。
  • 1
  • 2
  • 3
  • 4
  • 5

最后链接好的gcc版本如下:

alex@ubuntu:~$ gcc -v
Using built-in specs.
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu/Linaro 4.4.7-8ubuntu1' --with-bugurl=file:///usr/share/doc/gcc-4.4/README.Bugs --enable-languages=c,c++,fortran --prefix=/usr --program-suffix=-4.4 --enable-shared --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.4 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --disable-libmudflap --disable-werror --with-arch-32=i686 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.4.7 (Ubuntu/Linaro 4.4.7-8ubuntu1) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

这样gcc就安装完成了。

2.4 . gdb源码下载

ubuntu原生的gdb有bug,需要下载gdb源码并且修改这个bug后才能使用,所以需要下载gdb源码,并把gdb事先删除掉,删除命令为sudo apt-get autoremove gdb等待删除完成即可。
gdb源码下载为7.9版本。源码下载命令为:

wget http://ftp.gnu.org/gnu/gdb/gdb-7.9.tar.gz
  • 1

2.5. busybox源码下载。

	wget https://busybox.net/downloads/busybox-1.25.0.tar.bz2
  • 1

3. 已经下载源码的编译

对于以上源码有些bug需要fix,有些可以直接编译使用。所以需要编译才能使用。
安装之前一定要下载以下库文件,否则编译gdb或者linux内核时候可能会失败。

	sudo apt-get install aptitude
	sudo aptitude install libncurses5-dev
	sudo apt-get install libssl-dev
  • 1
  • 2
  • 3

3.1 gdb的修改以及编译。

编译之前我们已经在2.4节中对于gdb已经remve掉,如果没有确定是否reove掉可以使用gdb -v命令查看,如果还有版本信息则说明没有remove掉,需要重新remove掉。
gdb源码下载解压之后,以下操作全部在gdb解压目录完成。
需要更改gdb/remote.c中如下源码:

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

为如下:

if (buf_len > 2 * rsa->sizeof_g_packet) {
    rsa->sizeof_g_packet = buf_len;
    for (i = 0; i < gdbarch_num_regs (gdbarch); i++)
    {
        if (rsa->regs[i].pnum == -1)
            continue;
        if (rsa->regs[i].offset >= rsa->sizeof_g_packet)
            rsa->regs[i].in_g_packet = 0;
        else
            rsa->regs[i].in_g_packet = 1;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

对于此段的说明如下:修改gdb本地链接时候的栈区长度,把原先的错误判断更改为灵活栈区长度。对于gdb的能力不变。
运行如下命令配置,编译,安装gdb。

sudo ./configure 
sudo apt-get install libncurses5-dev ## 一定要安装此库,否则编译失败。
sudo make 
sudo make install
  • 1
  • 2
  • 3
  • 4

编译后的效果如下:
【强转】QEMU+GDB调试linux内核全过程
make install 命令之后效果:
【强转】QEMU+GDB调试linux内核全过程
验证:
gdb -v命令版本验证:

alex@ubuntu:~/Desktop/gdb-7.9$ gdb -v
GNU gdb (GDB) 7.9
Copyright (C) 2015 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-unknown-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word".
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

gdb7.9版本安装完毕。

3.2 linux内核编译

内核安装配置,make menuconfig
选择:kernel hacking,将frame size由1024改成2048即可。
如下图:
【强转】QEMU+GDB调试linux内核全过程
【强转】QEMU+GDB调试linux内核全过程

内核编译:
make -j4 数字根据自己的物理内核来判断。
编译后的效果图:
【强转】QEMU+GDB调试linux内核全过程

3.3 busybox的编译

解压完busybox并进入解压目录之后完成makefile的配置文件如下:

make defconfig
make menuconfig 
  • 1
  • 2

make menuconfig 选择配置时候应勾选如下配置:
跟配置选择“Busybody settings”–>“Build Options”–>“Build BusyBox as a static binary (no shared libs)”
具体每一步配置如下:
【强转】QEMU+GDB调试linux内核全过程
【强转】QEMU+GDB调试linux内核全过程
【强转】QEMU+GDB调试linux内核全过程
最后使用make -j4命令编译busybox;
测试busy_box可以在编译好的busybox跟目录使用如下命令测试,可以使用./busybox ls,如果测试命令跟ls命令效果一致,则说明busybox编译OK,否则找我也行,找度娘也行。
测试busybox效果如下:
【强转】QEMU+GDB调试linux内核全过程
上图可以看到编译时候产生了一个错误,不过没有关系,一样可以编译是OK的,只要有ls的效果就说明编译OK。
然后使用make install安装busybox,可以看到busybox跟目录下有一个"_install"目录。这个目录对于以后我们制作根文件系统很重要。

4.根文件系统的制作以及测试

4.1 根文件系统的制作

首先将上一步生成的_install文件夹复制到其他位置

 cd ..
 mkdir ramdisk
 cd ramdisk
 cp -r ../busy-1.25.0/_install/*  .
  • 1
  • 2
  • 3
  • 4

设置初始化进程init(建立一个软链接,一定不能直接复制过去)

cd ramdisk
ln -s bin/busybox init
  • 1
  • 2

设置开机启动程序

首先,我们需要先设定一些程序运行所需要的文件夹

mkdir -pv {bin,sbin,etc,proc,sys,usr/{bin,sbin},dev}
  • 1

init程序首先会访问etc/inittab文件,因此,我们需要编写inittab,指定开机需要启动的所有程序

cd etc
vim inittab
  • 1
  • 2

inittab文件的内容如下所示:

::sysinit:/etc/init.d/rcS   
::askfirst:-/bin/sh    
::restart:/sbin/init
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r
::shutdown:/sbin/swapoff -a
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

赋予可执行权限

chmod +x inittab
  • 1

编写系统初始化命令
从inittab文件中可以看出,首先执行的是/etc/init.d/rcS脚本,因此,我们生成初始化脚本

mkdir init.d
cd init.d
vim rcS
  • 1
  • 2
  • 3

rcS文件的内容如下所示:

#!/bin/sh

mount proc
mount -o remount,rw /
mount -a    
clear                               
echo "My Tiny Linux Starting, press enter to active"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

赋予可执行权限

chmod +x rcS
  • 1

在rcS脚本中,mount -a 是自动挂载 /etc/fstab 里面的东西,可以理解为挂在文件系统,因此我们还需要编写 fstab文件来设置我们的文件系统。

cd ramdisk/etc/
vim fstab
  • 1
  • 2

要挂载临时文件系统,固定的文件名为fstab, fstab文件内容如下:

#/etc/fstab
proc            /proc        proc    defaults          0       0
sysfs           /sys         sysfs   defaults          0       0
devtmpfs        /dev         devtmpfs  defaults          0       0
  • 1
  • 2
  • 3
  • 4

至此,我们已经完成了RAM Disk中相关文件的配置,可以压缩生成文件镜像了。

cd ramdisk
find . -print0 | cpio --null -ov --format=newc | gzip -9 > ../initramfs.img
  • 1
  • 2

最后生成的initramfs.img就是我们的根文件系统。

4.2 根文件系统的测试

运行如下命令测试根文件系统

qemu-system-x86_64 -kernel ./linux-2.6.32.20/arch/x86_64/boot/bzImage -initrd ./initramfs.img -append "console=ttyS0" -nographic
  • 1

测试效果如下:

【强转】QEMU+GDB调试linux内核全过程
按"enter"键进入用户界面。
下面对于qemu命令的一个解释:

	qemu-system-x86_64 命令对于你编译器对应的CPU版本,启动,也可以制作虚拟磁盘,下文会介绍;
	-kernel参数对应编译好的内核镜像的位置。
	-initrd参数对应的是根文件系统的位置。
	-append "console=ttyS0"参数为内核启动后传入参数,启动哪个termnal. 
	-nographic	无界面启动,启动在ubuntu本地终端里面。
  • 1
  • 2
  • 3
  • 4
  • 5

4.3 启动总结。

在本章中我们使用了第一章中讨论的除了gdb之外的全部文件,这些文件对应了我们在ubuntu14.04中使用编译好的镜像和制作好的根文件系统中的技术细节。
下一章重点讨论启动磁盘以及gdb调试问题。

5 gdb调试。

在第四章中我们讨论了在根文件系统中启动内核镜像的问题,在本章中我们重点介绍GDB调试以及qemu在gdb调试中的一些注意事项问题。
在4.2节中我们掌握了如何启动内核的问题。其实qemu在gdb调试中只要增加两个参数就可以:-S -s两个参数,总体命令如下:

qemu-system-x86_64 -kernel ./linux-2.6.32.20/arch/x86_64/boot/bzImage -initrd ./initramfs.img -append "console=ttyS0" -nographic
  • 1

这时候我们看到的启动的内核是没有打印输出的,是因为需要gdb配合才能够有打印输出。我们的gdb该出场了。我们使用如下命令:

	gdb vmlinux 
	### 参数对应的是编译好的内核根目录下的vmlinux文件。
  • 1
  • 2

效果图如下:

【强转】QEMU+GDB调试linux内核全过程
在没有GDB调试的情况下QEMU带-S -s参数默认阻塞。
需要启动gdb,如下:
【强转】QEMU+GDB调试linux内核全过程
附图中我按了两次continue,是因为我第一次continue之前做了一次break start_kernel操作,如果想一下子启动到终端界面,可以直接按continue。
如果想打断点,则需要ctrl +c暂定gdb即可设置断点。

OK,至此qemu+gdb调试内核代码全部介绍完毕,下一篇我们会介绍内核块设备驱动原理,届时会使用gdb调试内核代码。敬请期待。
<完>

查看更多关于【Linux系统】的文章

展开全文
相关推荐
反对 0
举报 0
评论 0
图文资讯
热门推荐
优选好物
更多热点专题
更多推荐文章
linux下如何单独编译设备树? linux设备树是什么
答: make vendor/device_name.dtb  如: make freescale/fsl-1043a-rdb.dtb

0评论2023-02-10369

移植linux3.7到nuc900系列开发板遇到的问题
通过移植学习linux新版本内核,大概了解一下内核变化。记录一下移植过程中遇到的问题或值得注意的地方。1,添加一款arm9芯片的支持首先修改\arch\arm\tools\mach-types文件添加一行w90p950evbMACH_W90P950EVBW90P950EVB同目录下的脚本文件在编译内核时会根据

0评论2023-02-10697

linux下安装redis3.2
这部分来自网络: http://blog.csdn.net/cuibruce/article/details/535015321.下载下载地址:http://www.redis.io/download选取当前最新版本3.2.1下载,上传到linux上,进行解压缩:[root@mongodb1 redis]# lsredis-3.2.1 redis-3.2.1.tar.gz进入redis-3.2.1目录

0评论2023-02-10962

终于解决了Linux下运行OCCI程序一直报Error while trying to retrieve text for error ORA-01804错误
终于解决了Linux下运行OCCI程序一直报Error while trying to retrieve text for error ORA-01804错误http://blog.csdn.net/zklth/article/details/7184032Linux下 和 Windows 下 Oracle Instant Client 的安装.http://fableking.iteye.com/blog/2115724 http

0评论2023-02-10637

linux lvm删除导致无法启动
要想编辑/etc/fstab文件,我们需要在系统中重新挂载根目录,使其具有可读写状态,使用如下命令:mount -o remount,rw /该条命令的作用是,以可读写的形式重新挂载根分区。然后再编辑/etc/fstab文件,就可以正常编辑。如下:

0评论2023-02-10931

linux中的strip命令简介------给文件脱衣服【转】
转自:http://blog.csdn.net/stpeace/article/details/47090255版权声明:本文为博主原创文章,转载时请务必注明本文地址, 禁止用于任何商业用途, 否则会用法律维权。作为一名Linux开发人员, 如果没有听说过strip命令, 那是很不应该的。 strip这个单词,

0评论2023-02-10728

linux下常用文件系统 linux支持的文件系统
不同的操作系统需要使用不同类型的文件系统,为了与其他操作系统兼容,以相互交换数据,通常操作系统都能支持多种类型的文件系统。Linux内核支持十多种不同类型的文件系统,下面对Linux常用的文件系统作一个简单介绍。ext2与ext3文件系统ext是第一个专门为Lin

0评论2023-02-10794

linux下将Python环境默认更改为Python3.6
步骤:#删除原来指向python2的软链接sudo mv /usr/bin/python /usr/bin/python.bak #/usr/local/python3.6/bin/python3.6 这个路径为实际的python3.6的bin文件夹下的Python3.6的路径,这个按照自己的实际情况进行更改 sudo ln -s /usr/bin/python3.6 /usr/bin

0评论2023-02-10852

Linux更改SSH默认端口 linux设置ssh端口
1.修改ssh配置文件  vim /etc/ssh/sshd_config  将 #Port 22 改为 Port 10023(更改的端口号最好在1024~65535间,不和其他服务端口冲突就ok)2.关闭防火墙  systemctl stop firewalld.service3.重启ssh服务  systemctl restart sshd.service4.新建ssh

0评论2023-02-10765

mongodb 对内存的占用监控 ——mongostat,linux系统可用的内存是free + buffers + cached
刚开始使用mongodb的时候,不太注意mongodb的内存使用,但通过查资料发现mongodb对内存的占用是巨大的,在本地测试服务器中,8G的内存居然被占用了45%。汗呀。 本文就来剖析一下mongodb对内存的具体使用方法,以及生产环境针对mongodb占大量内存的问题的解决

0评论2023-02-10641

linux grep命令参数及用法详解---linux管道命令grep
功能说明:查找文件里符合条件的字符串。语  法:grep [-abcEFGhHilLnqrsvVwxy][-A显示列数][-B显示列数][-C显示列数][-d进行动作][-e范本样式][-f范本文件][--help][范本样式][文件或目录...]补充说明:grep 指令用于查找内容包含指定的范本样式的文件,

0评论2023-02-10315

更多推荐