ubuntu: qemu+gdb 调试linux kernel 学习笔记
声明:
本笔记内容并非本人原创,90%来自网络资料的整合。同时,由于自己是刚刚接触qemu & gdbserver remote debug,本文也就算不得教程,仅供有缘人参考而已。
------------------------------------------------------------------------------------------------分割线---------------------------------------------------------------------------
step 1: kernel 编译环境安装
apt-cache search build-essential
sudo apt-get install build-essential -y apt-cache search libncurses-dev
sudo apt-get install libncurses-dev -y
当然,可能还需要其他一些工具,如果gcc g++ make 之类的工具,毕竟build-essential是一个工具箱子,若有洁癖,可能就有点冲突。而ncurses-dev,这个是必须要有的,我记得在fedora上是直接yum install ncurses-dev即可,.deb系列的似乎是加了个前缀。
step 2: gdb的安装
需要告诉的是,build-essential 里应该是包含了一个gdb & gdbsever工具了,但是很抱歉的是无法使用,会出现这个错误:
Remote 'g' packet reply is too long: 000000000000000020000000000000004000000000000000001006000000000000f009000000000028aece81ffffffff981fc081ffffffff901fc081ffffffff0030c1010000000000000000000000000000000000000000f0b926020000000020f1d281ffffffffb01fc081ffffffff00e0e681ffffffff0010e781ffffffff02fbd281ffffffff9600000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007f0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000801f0000
于是,我们需要去下载一个比较新的gdb source下来(我使用的是7.8),网址是: http://ftp.gnu.org/gnu/gdb/
http://ftp.gnu.org/gnu/gdb/
然后按照网络前人们共享出来的资料,修改gdb的源码: 在 gdb-7.8/gdb/remote.c 文件的 static void process_g_packet (struct regcache *regcache)函数里面修改部分内容,如下:
static void
process_g_packet (struct regcache *regcache)
{
struct gdbarch *gdbarch = get_regcache_arch (regcache);
struct remote_state *rs = get_remote_state ();
struct remote_arch_state *rsa = get_remote_arch_state ();
int i, buf_len;
char *p;
char *regs; buf_len = strlen (rs->buf); /* Further sanity checks, with knowledge of the architecture. */
/* if (buf_len > 2 * rsa->sizeof_g_packet)
error (_("Remote 'g' packet reply is too long: %s"), rs->buf);
*/
/*modify by xx*/
if (buf_len > * rsa->sizeof_g_packet) {
rsa->sizeof_g_packet = buf_len;
for (i = ; i < gdbarch_num_regs(gdbarch); i++) {
if (rsa->regs[i].pnum == -)
continue;
if (rsa->regs[i].offset >= rsa->sizeof_g_packet)
rsa->regs[i].in_g_packet = ;
else
rsa->regs[i].in_g_packet = ;
}
}
//.......
}
}
}
上面的14-15行是原来文件的,而18-27行是重新添加上的 <为了节约版面,我没有贴后面的,所以,注意 " { } " 可能导致的语法错误>,这样修改的具体原理,本人并不清楚,但确实解决了问题。
修改完整后,就开始编译gdb吧。在 gdb-7.8/ 下执行下面的命令:
./configure --prefix=../../tools/
make
make install
需要注意的是在gdb-7.8/ 目录下并没有Makefile文件,需要使用 ./configure来生产。在配置的时候,如果要指定gdb安装的路径(目录),那么就需要跟上 --prefix=$PATH的相关参数,一般这种情况可能会针对系统已经有一个gdb了但无法使用,同时也未删除,那么新编译的gdb可能需要安装在另外的目录了。当然我自己的是安装在 ../../tools/ 目录下。
step 3: 编译linux kernel
去 www.kernel.org下载自己需要的版本,待完毕后,对kernel编译生成bzImage & vmlinux 文件。如果是和我一样刚入门的,可以参考以下命令&步骤:
cd linux-3.12./
cp /boot/config-3.13.--generic .config
make menuconfig
<save>
make bzImage
需要说明的是,具体要看哪些调试信息,应该在make menuconfig的时候去配置,去选择,然后保存好后,就编译。编译后,bzImage这个是被压缩了的,供qemu虚拟机使用,vmlinux里面带了某些信息,没有压缩,供gdb使用。
当编译结束后,可以将vmlinux bzImage文件copy到一个干净的目录下吧---这个随自己的习惯了,不copy也无所谓了。
上面忘记了准备最重要的东西了: qemu
step 4: qemu的使用
简单说下: qemu 是一款虚拟机,可以模拟x86 & arm 等等硬件平台<似乎可模拟的硬件平台很多...>,而qemu 也内嵌了一个 gdbserver。这个gdbserver于是就可以和gdb构成一个远程合作伙伴,通过ip:port 网络方式或者是通过串口/dev/ttyS*来进行工作,一个在这头,一个在那头。
至于安装qemu虚拟机,可以通过源码编译,make & make install ,在这里可以下载:http://wiki.qemu.org/Download。也可以直接在ubuntu 软件包里apt-get install qemu-kvm即可。这里不详细记载了。当安装后,可能的文件是这些:
qemu-system-i386 qemu-system-x86_64 qemu-img qemu-io
....
这个是什么意思呢? 第一行的表示是 i386机器上使用的qemu虚拟机,第二行表示是 x86_64上使用的虚拟机。另外的就没使用过了。具体的请参考官网文档:http://wiki.qemu.org/Main_Page。当然,我自己的系统是 x86_64的,使用的是第二个。
step 4: 让kernel为你稍带片刻~
qemu-system-x86_64 -kernel ./bzImage -initrd ./initrd.img -smp -gdb tcp:: -S
先使用命令启动qemu。
qemu-system-x86_64的参数比较多,这里简单说下:
-kernel 是指定一个大内核文件,当仁不让的是bzImage。
-initrd 是指定一个 initrd.img文件,这个文件可以从 /boot/initrd.img-3.13.0-43-generic 拷贝而来,关于它是什么东西呢? 可以参考这个:http://www.linuxfly.org/post/94/ ,或者是这个http://blog.csdn.net/chrisniu1984/article/details/3907874 。
-smp 可以从名字猜想,它是给qemu指定几个处理器,或者是几个线程<嗯,大概意思就thread吧>。
-gdb则是启动qemu的内嵌gdbserver,监听的是本地tcp端口1234---如果这样写: -gdb tcp:192.168.1.100:1234 ,似乎也是没问题的。
-S 就是挂起gdbserver,让gdb remote connect it。还有一个-s,那是另外一种情况要使用了。
如果自己嫌敲命令麻烦<虽然那很酷>,可以使用以下的方式,将该命令保存到某个文件中,比如 qemu.start:
#!/bin/bash
qemu-system-x86_64 -kernel ./bzImage -initrd ./initrd.img -smp -gdb tcp:: -S
<save>
chmod +x qemu.start ./qemu.start
这样就可以启动qemu了 <注意自己的 bzImage & initrd.img 文件的路径>
提示: man qemu-system-x86_64,你会获得一些帮助。
step 5: 使用gdb去连接已将启动了的qemu:
../tools/gdb/bin/gdb vmlinux -----
GNU gdb (GDB) 7.8
Copyright (C) Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 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"...
Reading symbols from vmlinux...done.
----- (gdb) target remote :
Remote debugging using :
0x0000000000000000 in irq_stack_union () (gdb) b start_kernel
Breakpoint at 0xffffffff81d2fb02: file init/main.c, line . (gdb) c
Continuing. Breakpoint , start_kernel () at init/main.c:
{ (gdb) n
smp_setup_processor_id();
(gdb) n
boot_init_stack_canary();
(gdb) n
cgroup_init_early();
第一行表明启动我自己编译的gdb,这有两个方式 : gdb fileName 启动,或者 gdb启动后,再使用 file fileName 启动
第21行表明连接远程gdbserver,由于这是在同一台笔记本上,就没有指定ip地址,仅仅指定了port号码。----当然,如果是连接uart口,也行。
第25行,是break一个断点,在某个函数的入口处 。
第28行,应该是发一个命令,让qemu那边继续运行的意思,这个时候,qemu那边的屏幕上会闪现出:"Booting from ROM..."
后面啊,就是下一步下一步的意思咯: next ... next ... 当然,也可以选择step step s.... 直到哪里才会在qemu那边打印消息呢? 要在 console_init();这行代码后才会的。
做一个稍微重要的说明: 我这里并没有启用文件系统,如果有需要,可以试着用busybox做一个,然后参考qemu kernel调试手册,或者网络资源进行加入调试即可。
--------------------------------------------------------------------------------------扯淡分割线--------------------------------------------------------------------------------------------
后记:
至于gdb 的命令,还有很多很多,如果是new to kernel的话,请点击这里: http://www.sourceware.org/gdb/ 最好的是慢慢啃官网文档,然后再看看别人的理解,应该就差不多了。或者看看这个:http://www.yolinux.com/TUTORIALS/GDB-Commands.html
这几天也一直在搜索kernel debug的方法,qemu+gdb 是一种,当然也还有其他的方法。不过总结下来,代价以qemu+gdb最小。如果你是大屏幕pc,可以试试将qemu+gdb+eclipse这样,纳入IDE环境。而自己是笔记本,就不凑合IDE了,在vim shell 下足以。
稍微夹杂一点想法: 前面也是看了一些操作系统的书+linux kernel的入门读物,但是一直没机会去试着单步运行以下kernel,看看它是怎么走的<书中搭建方式花销比较大:要么就是两台电脑,要么就是搞一半就会放弃的那种>。久而久之,也就懈怠了,更别说再去详细的看代码了。linux kernel是真的很伟大,但没必要神话它。如果对操作系统原理和程序设计的理解达到一定水平,自己也可以整一个OS---尽管那可能会很粗糙。于是,知行合一也就有必要了。
最后就是,如果真对kernel有兴趣,那起码得把英语搞一搞,然后尽早关注kernel MailList----虽然是万变不离其宗,但世界也是发展变化的。书上多少是有时限的。
关键字: qemu kernel gdb gdbserver 调试
ubuntu: qemu+gdb 调试linux kernel 学习笔记的更多相关文章
- linux kernel学习笔记-5内存管理_转
void * kmalloc(size_t size, gfp_t gfp_mask); kmalloc()第一个参数是要分配的块的大小,第一个参数为分配标志,用于控制kmalloc()的行为. km ...
- 在qemu环境中用gdb调试Linux内核
简介 对用户态进程,利用gdb调试代码是很方便的手段.而对于内核态的问题,可以利用crash等工具基于coredump文件进行调试.其实我们也可以利用一些手段对Linux内核代码进行gdb调试,qem ...
- 利用QEMU+GDB搭建Linux内核调试环境
前言 对用户态进程,利用gdb调试代码是很方便的手段.而对于内核态的问题,可以利用crash等工具基于coredump文件进行调试. 其实我们也可以利用一些手段对Linux内核代码进行gdb调试,qe ...
- linux 驱动学习笔记01--Linux 内核的编译
由于用的学习材料是<linux设备驱动开发详解(第二版)>,所以linux驱动学习笔记大部分文字描述来自于这本书,学习笔记系列用于自己学习理解的一种查阅和复习方式. #make confi ...
- Linux内核学习笔记-2.进程管理
原创文章,转载请注明:Linux内核学习笔记-2.进程管理) By Lucio.Yang 部分内容来自:Linux Kernel Development(Third Edition),Robert L ...
- Linux内核学习笔记-1.简介和入门
原创文章,转载请注明:Linux内核学习笔记-1.简介和入门 By Lucio.Yang 部分内容来自:Linux Kernel Development(Third Edition),Robert L ...
- Linux内核学习笔记二——进程
Linux内核学习笔记二——进程 一 进程与线程 进程就是处于执行期的程序,包含了独立地址空间,多个执行线程等资源. 线程是进程中活动的对象,每个线程都拥有独立的程序计数器.进程栈和一组进程寄存器 ...
- 尚硅谷韩顺平Linux教程学习笔记
目录 尚硅谷韩顺平Linux教程学习笔记 写在前面 虚拟机 Linux目录结构 远程登录Linux系统 vi和vim编辑器 关机.重启和用户登录注销 用户管理 实用指令 组管理和权限管理 定时任务调度 ...
- Linux系统学习笔记:文件I/O
Linux支持C语言中的标准I/O函数,同时它还提供了一套SUS标准的I/O库函数.和标准I/O不同,UNIX的I/O函数是不带缓冲的,即每个读写都调用内核中的一个系统调用.本篇总结UNIX的I/O并 ...
随机推荐
- Android Service 服务
一. Service简介 Service是android 系统中的四大组件之一(Activity.Service.BroadcastReceiver.ContentProvider),它跟Activi ...
- selenium python (十五)控制滚动条操作
#!/usr/bin/python# -*- coding: utf-8 -*-__author__ = 'zuoanvip' #一般用到操作滚动条的两个场景 #注册时的法律条文的阅读,判断用户 ...
- 性能测试之系统监控工具nmon
一.概述 本篇文章主要讲解nmon,以下为目录 1.nmon介绍 2.nmon下载.安装及使用 3.nmon analysis 分析及使用,各个项的含义 二.详细信息: 1.nmon介绍: nmon( ...
- js保留小数点后N位的方法介绍
js保留小数点后N位的方法介绍 利用toFixed函数 代码如下 复制代码 <script language="javascript"> document.write( ...
- jQuery文档加载完毕的几种写法
js中文档加载完毕.一般在body加一个onload事件或者window.onload = function () {} jQuery中有好多写法,平时也不注意,别人一问,还真觉得头大. 下面是我整理 ...
- delphi 中怎么知道某一个月有多少天
if (month in (1,3,5,7,8,10,12)) return 31; else if (month in(4,6,9,11)) return 30; else if (year 是闰年 ...
- 【原创】开发Kafka通用数据平台中间件
开发Kafka通用数据平台中间件 (含本次项目全部代码及资源) 目录: 一. Kafka概述 二. Kafka启动命令 三.我们为什么使用Kafka 四. Kafka数据平台中间件设计及代码解析 五. ...
- Azure杂七杂八系列(二) - 如何在Azure上重新配置VM
我们经常遇到这样的问题, 对于已经建立的VM进行性能提升, 比如需要更好的虚拟机或者需要迁移到其他的虚拟网络 那么我们可以使用以下的方法进行修改. 1. 如图所示, TESTVMXX位于North ...
- 桶排序-Node.js
, , , , ]; var a = [], i; ; i < b.length; i++) { var num = b[i]; a[num] = a[num]||; a[num] ++; nu ...
- 深入.Net字符串类型
.Net的字符串其实还是有很多东西可以写的.但是最近在学习SQL Server,只好先做下最近学习到的一些巧用,妙用之类的东西. 巧用String.Join拼接字串数组,字符串集合为字符串.如果在之前 ...