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

   2023-03-08 学习力0
核心提示:昨天更新了一篇名为《QEMU+GDB调试linux内核全过程》[link][https://blog.csdn.net/weixin_37867857/article/details/88138432]的博客,发现排版比较混乱,而且思维也比较混乱。咋一看下来简直是惨不忍睹,而且会给读者在安装过程中一种云里雾里的感觉,加上

昨天更新了一篇名为《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调试内核代码。敬请期待。
<完>

 
反对 0举报 0 评论 0
 

免责声明:本文仅代表作者个人观点,与乐学笔记(本网)无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
    本网站有部分内容均转载自其它媒体,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责,若因作品内容、知识产权、版权和其他问题,请及时提供相关证明等材料并与我们留言联系,本网站将在规定时间内给予删除等相关处理.

  • Linux下Bochs,NASM安装和使用 linux bom
    Linux下Bochs,NASM安装和使用 linux bom
    以Ubuntu为例,先更新一下:sudo apt-get updatesudo apt-get upgrade然后安装Bochs环境:sudo apt-get install build-essential xorg-dev libgtk2.0-dev安装NASMNASM官网下载,这以nasm-2.14.02.tar.gz为例:用tar zxvf nasm-2.14.02.tar.gz解压后编译安装cd
    03-08
  • 把玩Alpine linux(一):安装
    把玩Alpine linux(一):安装
    导读Alpine Linux是一个面向安全应用的轻量级Linux发行版。它采用了musl libc和busybox以减小系统的体积和运行时资源消耗,同时还提供了自己的包管理工具apk。Alpine 的内核都打了grsecurity/PaX补丁,并且所有的程序都编译为Position Independent Executabl
    03-08
  • 日志审计与分析实验三(rsyslog服务器端和客户端配置)(Linux日志收集)
    日志审计与分析实验三(rsyslog服务器端和客户
     Linux日志收集一、实验目的:1、掌握rsyslog配置方法2、配置rsyslog服务收集其他Linux服务器日志:C/S架构:客户端将其日志上传到服务器端,通过对服务器端日志的查询,来实现对其他客户端的日志进行集中管理;下面实现就是通过两套机器来实现,(server:19
    03-08
  • Linux学习系列--如何在Linux中进行文件的管理
    Linux学习系列--如何在Linux中进行文件的管理
    文件在常见的Linux的文件系统中,经常使用能了解到的文件管理系统是分为多个文件夹进行管理的。如何查看文件路径 pwd ,在文件目录中,会有一个点(.)代表的是当前目录,两个点(..)代表的是当前目录的上层目录在Linux下,所有以点开始的文件都是“隐藏文件
    03-08
  • [JetBrains] 我想在 Linux 上使用 macOS 键绑定!
    [JetBrains] 我想在 Linux 上使用 macOS 键绑定
    很高兴认识你,我的名字是kitakkun。我最近开始实习,是工程界的新手。顺便说一句,这是我的第一篇文章。你最喜欢的操作系统是什么?视窗?苹果系统?还是Linux?我将它们全部用于不同的目的,但感觉就像 macOS ≒ LinuxWindows。一两个月前,我最喜欢 Linux
    03-08
  • linux 配置Socks51
    linux 配置Socks51
    ***大家耳熟能详,但是socks用到的人比较少,那什么是socks呢?请看第二段或者百度百科,socks分别有4和5两个版本,现在5为主流。工作中经常用***访问国外,但是同时国内的速度又慢了,让人很纠结,实际上这个时候可以考虑使用socks。指定某一个程序使用国外s
    02-10
  • linux下如何单独编译设备树? linux设备树是什
    答: make vendor/device_name.dtb  如: make freescale/fsl-1043a-rdb.dtb
    02-10
  • linux下mysql开启远程访问权限及防火墙开放3306端口
    linux下mysql开启远程访问权限及防火墙开放3306
    开启mysql的远程访问权限默认mysql的用户是没有远程访问的权限的,因此当程序跟数据库不在同一台服务器上时,我们需要开启mysql的远程访问权限。主流的有两种方法,改表法和授权法。相对而言,改表法比较容易一点,个人也是比较倾向于使用这种方法,因此,这
    02-10
  • 移植linux3.7到nuc900系列开发板遇到的问题
    通过移植学习linux新版本内核,大概了解一下内核变化。记录一下移植过程中遇到的问题或值得注意的地方。1,添加一款arm9芯片的支持首先修改\arch\arm\tools\mach-types文件添加一行w90p950evbMACH_W90P950EVBW90P950EVB同目录下的脚本文件在编译内核时会根据
    02-10
  • 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目录
    02-10
点击排行