Linux内核调试技术指南

前两天,完成了ucos在2440上的移植,以及boot的修改。今天突然想到,我在linux下,该如何来编写,调试比较复杂的驱动。我想这个问题应该从如何调试内核入手,先转载两个文字,待西西看来。

系统搭建过程中,对于系统平台搭建工程师在完成Bootloader 的 调试之后就进入Kernel 裁减移植的阶段,其中最重要的一步是 Kernel 启动的 调试,在 调试Kernel过程中通常遇到最常见的问题是启动异常:

UncompressingLinux............................................................

........................... done, booting the kernel.( 挂死在此处)

 

注意:这里是arch/arm/boot/compressed/head.S的解压过程,调用了decompress_kernel()(同目录下的 misc.c)->include/asm-arm/arch-xxx/uncompress.h的putc()实现。这是在uboot中初始化的,用的是物理地址,因为此时内核还没有起来。

而 printascii则是调用了汇编。printascii()位于arch/arm/kernel/debug.S,他需要调用虚拟地址,此虚拟地址通过machine_start提供,而相关的宏在include/asm/arch-xxx/debug-macro.S实现,这下明白了。

10-05-14添加:debug.s里面需要判断一下当前是否打开了mmu,然后指定uart的基址。在解压阶段的head.s,mmu是1:1映射,目的是加快速度。到了内核的head.s,就是真正的mmu了,此时就是虚拟地址了。


导致驱动异常(启动挂死)的原因有很多,如基于EVM 板的硬件做了修改(如更改了FLASH 空间大小、地址和型号,更改了SDRAM 、DDR SDRAM 空间大小、地址和型号,更改了晶振频率等),板卡ID号不支持等。那么如何进行调试那,其实有两种调试技术比较有效。

Kernel 启动调试技术- 使用printascii() 函数跟踪start_kernel() 有没运行 ,在booting the kernel 之后Kernel 最先执行的是start_kernel() 函数,确认start_kernel() 有否执行就是在其开始代码段添加printascii("start_kernel …"),如果串口没有打印出start_kernel …,说明start_kernel() 没有运行,那么可能的原因有Bootloader 配置的启动参数错误、 Kernel 加载到(DDR) SDRAM 的地址不正确,Kernel 编译时指定的(DDR) SDRAM 运行地址不正确等。这样就需要一项一项排查错误,当错误被排查完毕,通常打印出 start_kernel …是种必然,如果打印出这仪信息说明Kernel已 进入到start_kernel() 执行,如果此时有串口启动打印就比较成功了,如果仍然没有打印启动信息,就需要另外一种调试技术。

附代码修改:init/main.c <<-

extern void printascii(const char*);     // Modify

asmlinkage void __init start_kernel(void)

{

    char * command_line;

    extern struct kernel_param __start___param[], __stop___param[];

    printascii("start_kernel …");        // Modify

    smp_setup_processor_id();

->>

Kernel 启动调试技术- 使用printascii() 函数打印printk() 缓存信息 ,如果Kernel已进入到start_kernel() 执行,仍然没有启动信息打印出来,说明串口波特率出问题的可能性比较大,启动信息是暂时缓存到临时buffer--printk_buf 中的,进入start_kernel() 中会对串口波特率重新初始化,当初始化完成后,缓存的系统启动信息便打印出来,不能打印说明用于串口波特率初始化的系统时钟源没有初始化正确,通常是系统时钟源和实际的晶振频率不一致导致的,通常排查和解决这个问题后,系统启动信息是能正确打印的。为了帮助解决问题,可以使用 printascii() 打印printk_buf内容。这样就能把printascii ()打印的系统信息和预想的系统信息进行比较,从而加快解决问题的进度。

附代码修改:kernel/printk.c   <<-

extern void printascii(const char*);    // Modify

static char printk_buf[1024];           // Modify

asmlinkage int printk(const char *fmt, ...)

{

    va_list args;

    int r;

    va_start(args, fmt);

    r = vprintk(fmt, args);

    va_end(args);

    printascii(printk_buf);            // Modify

    return r;

}

static int recursion_bug;

static int new_text_line = 1;

//static char printk_buf[1024];        // Modify

->>

如上是Kernel 裁减移植过程中最重要的两个启动调试技术,灵活使用将带来工作效率的提升,不管硬件平台是那种ARM 或者其它类型的CPU ,也不管是哪个 Kernel 版本(如Linux-2.6.24 、Linux-2.6.30 等 都可以采用这两个启动调试技术解决实际问题。为了支持 printascii() 函数,需要在 Kernel 裁减中(make menuconfig )添加Kernel hacking ->[*]Kernel low - level debugging functions 的支持。

 

我的补充:

1/ 可以在/kernel/head.s里添加打印看是否跑到mmu开启前:


__turn_mmu_on:

    //打印一个字符a

    mov r9,r0

    mov r0,'a'

    bl printascii //该函数位于arch/arm/kernel/debug.s,调用了include/mach/debug-macro.S

    mov r0,r9
    //现在开启mmu
    mov    r0, r0
    mcr    p15, 0, r0, c1, c0, 0        @ write control reg
    mrc    p15, 0, r3, c0, c0, 0        @ read id reg
    mov    r3, r3
    mov    r3, r3
    mov    pc, r13    /*实际调用了__switch_data,在head-common.s*/


2/ 一般按楼上方法,在startkernel就可以打印出来,如果:在第一步可以打印,而开启mmu后不能打印,那绝对是虚拟地址映射问题,这个问题我搞了2天了....

3/ 如果还没有反应,就要检查串口打印那段 debug-macro.S 是否有问题了。

总结一下:

/compressed/head.s和/kernel/head.s基本上不用改,看文件头,2001年写的,就知道了.呵呵.

 

 

linux内核调试指南
一些前言
作者前言
知识从哪里来
为什么撰写本文档
为什么需要汇编级调试
***第一部分:基础知识***
总纲:内核世界的陷阱
源码阅读的陷阱
代码调试的陷阱
原理理解的陷阱
建立调试环境
发行版的选择和安装
安装交叉编译工具
bin工具集的使用
qemu的使用
initrd.img的原理与制作
x86虚拟调试环境的建立
arm虚拟调试环境的建立
arm开发板调试环境的建立
gdb基础
基本命令
gdb之gui
gdb技巧
gdb宏
汇编基础--X86篇
用户手册
AT&T汇编格式
内联汇编
汇编与C函数的相互调用
调用链形成和参数传递
C难点的汇编解释
优化级别的影响
汇编基础--ARM篇
用户手册
调用链形成和参数传递
源码浏览工具
调用图生成工具
find + grep
wine + SI
global
Source-Navigator
vim + cscope/ctags
kscope
lxr
SI等与gdb的特点
调用链、调用树和调用图
理想调用链
函数指针调用
调用链的层次
非理想调用链
调用树与调用图
穿越盲区
穿越gdb的盲区
穿越交叉索引工具的盲区
工程方法
bug 与 OOPS
***第二部分:内核分析***
调试相关子系统
kgdb源码分析
sysrq
oprofile
kprobes
驱动分析
载入模块符号
seq_file.c的分析
module.c的分析
中断处理过程
s3c24xx内存初始化分析
虚拟地址空间
用户层的观察窗
交互,从内核层分析
理解设备模型
面向对象的实现
设备模型的分层
外围支持机制
文件系统
***第三部分:其他工具***
strace
ltrace
SystemTap
MEMWATCH
YAMD
Magic SysRq
附录:社区交流相关
补丁提交相关文档
补丁制作与提交示范
git使用
附录:内核参考书籍文章
私人备忘
linux内核调试指南
大海里的鱼有很多,而我们需要的是鱼钩一只
本文档由大家一起自由编写,修改和扩充,sniper负责维护。引用外来的文章要注明作者和来处。本文档所有命令都是在ubuntu/debian下的操作。选取的内核源码从文档开始编写时最新的内核版本–2.6.26开始,而且会随着linux的更新而不断更换新的版本。所以文档的内容可能前后不一致。相信大家有能力克服这个问题。

本文档的字符图示在linux环境下显示正常,在window下显示有细微的错乱。

本文档唯一的更新网址是:http://wiki.zh-kernel.org/sniper 转载请保留此网址。

有任何建议请发邮件:[email protected]

有任何问题请到邮件列表提问:http://zh-kernel.org/mailman/listinfo/linux-kernel

一些前言
作者前言
一个人默默地敲打这篇文章也有段时间了。在这个过程里,没有收到任何的赞誉,也没接到任何的板砖,没有任何的反馈。就这么敲打着,修理着。但是本人从没怀疑这篇文档的价值,这是因为,本人就是这篇文档的亲身收益者。在这里把它“无私”奉献出来,乃是出于对于某类同道者锲而不舍孜孜以求的“德性”的认同和“同情”,你的痛苦我表示感同身受,你的迷茫我愿意一起分担。一定有人能从个文档受益,这便已让我知足。其实,写这个文档并非是件苦差,而是字字都是有感而发的,不吐不快的结果。这里的句句都是本人教训和经验的记录。

谈到调试器,世上存在两种截然不同的看法。其中一种,是超级解霸的作者,他认为“程序不是写出来的,好程序绝对是调试出来的”。对于这个观点,虽然本人学识浅陋,也很崇拜“ ”他的为人,但是本人还是持着极不认同的态度。而第二种相反观点的人,便是linux之父linus了。他认为调试器只会“误人子弟”,只会导致人们迷于表象而不去真正理解源码本身。并以此为由,长期没把kgdb内置到内核中。对于调试调试bug会引入错误的修正这个观点,我认为还是有点道理的。但是他以此为由而不把它集合到内核中,这个做法我就认为是毫无道理了。因为linus本人就说过:“我只使用GDB,而且我总是并不把它作为调试器来使用,只是将其作为一个可以用来分析程序的分解器来使用。”既然他可以这样做,为什么就认定他人使用gdb的目的一定就是用来调试bug而不是另有所用呢?本人之所以这样说,这是因为本人正也是使用gdb主要是用来辅助分析内核代码而不是主要用来调试错误的。这也正就是本文的主题。

世上从不缺少解决问题的答案,缺少的是解决问题的方法。现在,linux的世界里已经不缺少牛书了,将尽一千页一本的满载答案的砖头书接踵而来,但是渐渐地发现,看书看到后面就忘了前面,回到前面有忘了后面,甚至一个章节还没看完,那个子系统已经被完全重写了。慢慢地,就会怀疑“我是不是真的变老了?真的不行了?”但是我们从没想过:“凭什么我们就如此受制于人?他就能搞懂,而我就不行呢?”。其实,我们需要的是一种重其意而忘其形的根本之道,需要的是一种兵来将挡,火来水淹的通用解决方法。而绝不是淹没于牛人们的结论中。否则,遇到一个新的问题,就只能埋怨牛人的书还不够厚,以至于没把你需要的东西也包括进去了。牛人一定有一套牛方法,而他在书中不详说,我不认为是他故意“留一手”,而是认为这是对自身觉得习以为常的事物的一种疏忽。牛人的研究结果其实不是最重要的,他的研究方法和手段才是最重要的事情。而我,也渐渐地发现,调试器能带给我们很多有用的提示,使得我们能不断的寻找到思考的灵感和方向,也使得学习变得非常的有趣性和有目的性。我想,利用调试器辅助源码分析,是不是正是很多牛人正在做的而没有说出来的事情呢?无论答案如何,本人还是觉得,调试器是个好东西,不要轻易把它搁置在一旁。虽然很多高人也许已经是深安此道,甚至已经不需要它的提示了,但是它依然有益于我等功力尚浅的人。把这种经验和技巧记录下来,让需要这项技巧的人少化时间去摸索,这绝对不是一件坏事。

正是因为这个原因,随着文档慢慢地变大,也更加的觉得文档的题目起得有点不恰当了,题目起作“内核动态分析指南”更恰当点。文档的主旨是利用调试器动态分析内核,调试错误只是这个过程的副产品罢了。不过,这个新的名字实在是不够现在名字“刺眼”,所以也就没有启用它。

说了这么多的废话和出格的话,无非是有两个目的:这个文章慢慢的变得这么长了,如果没有半句的“人”话,没有半句的现实世界中的语句。那估计本人不是变成了机器人,阅读的人也会变成了机器人。顺便借这段文字交交朋友。另一个目的呢,是说不应拘束于工具,工具是死的,人是活的。如果某些工具确能带给我们某些有益的提示,我们就可以去尝试它,取起优点而舍其糟粕。

引用的原文:

Linus 谈调试器和内核如何发展:http://www.bitscn.com/linux/kernel/200604/7493.html

知识从哪里来
1. 永远不要忘记的三大帮助命令

XXX -h(xxx –help)
man -a XXX
info XXX
2. 如何安装帮助文档

$ sudo synaptic 界面出来后,在“组别”->“文档”选取你要的文档进行安装
或$ apt-cache search Documentation | grep XXX 搜索需要的文档进行安装
3. 从软件/工具的官方网站阅读/下载文档

4. 从irc获取帮助 irc.freenode.net

5. 从邮件列表获取帮助 mailist http://lkml.org/ http://marc.info/

6. 发行版社区文档或社区 https://help.ubuntu.com/community/http://wiki.ubuntu.org.cn/

7. 利用google搜索文档或阅读他人文章

8. 利用google搜索lkml

http://www.google.cn/advanced_search?hl=zh-CN 网域那里填上lkml.org

9. 获取内核文档

源码本身
源码中的注释
内核源码附带的文档 Documentation
相关的教科书
论文 免费论文引擎 http://citeseerx.ist.psu.edu/
内核子系统的官方网站
获取内核源码目录Documentation/DocBook/ 下已经编译好的书籍
找到最新版本的文档
$ apt-cache search linux-doc  
安装最新的文档    
$ sudo apt-get install linux-doc-2.6.24    
阅读Documentation/DocBook/ 下已经编译好的书籍(html格式)
$ firefox /usr/share/doc/linux-doc-2.6.24/html/index.html         
10. 买书

11. 书籍最后面的参考书目

12. 文章末尾的参考文章

为什么撰写本文档
todo:学习方法,学习曲线,参考书籍的特点和不足,本文档的任务

内核学习曲线

1.只读书不看源码

参考书籍:Linux Kernel Development

2.参考源码读书(读书为主)

参考书籍:understanding the linux kernel

3.参考书读源码(看源码为主)

参考书籍:情景分析

4.只看源码不/少读书(提交补丁为主)

参考:lkml,main-tree, mm-tree

linux内核分析方法

按分析的对象分:

1.代码: 分析的对象是源代码

2.数据: 分析的对象是内核运行时产生的数据

按观察对象的状态分:

1.静态: 观察的目标对象是静止不动的

2.动态: 观察的目标对象是动态变化的

所以综合地看,分析方法的种类有:

1.静态代码:

最原始的方式,阅读源代码

2.动态代码:

利用某些工具或手段,动态分析源代码。又分为

a. 利用lxr, cscope, source insight等工具交叉索引源代码

b. 利用git,web-git通过阅读增量patch等形式观察源码的进化

c. 利用调试器跟随内核的运行动态观察内核正在运行的代码片段

3.静态数据:

观察的对象是内核在运行时产生或收集汇总出来的数据。又分为

a. 代码中printk语句打印出来的内核信息

b. 系统出错产生的oops,panic信息

c. 借助systemtap等类似工具提取的内核数据汇总

4.动态数据:

借助内核调试器实时观察内核不断产生的数据

可见内核调试器是最强大的内核分析工具,但它也不是“全功能”的工具。

1. 主要地,本文档聚焦于描述如何利用gdb对内核进行源码级别和汇编级别的观察和调试

而这种调试的目的有两个:

确定bug产生的引入点。这部分内容放于本文档第一部分。 
配合源码阅读工具(source insight,kscope等),观察内核实时运行的状况,观察内核数据的产生和变化,以及观察各个函数的动态调用关系,从而以一种精确的动态的和验证性的方式来理解内核运作的原理。这部分内容放于本文档第二部分
前者是调试器应用的主要价值,而后者却是本文档的兴趣所在。

2. 因为需要观察用户层和内核层的交互,演示调试工具的全面功能等原因,本文档内容不完全局限于内核层。

3. 另外,为了提供内核调试知识的全面叙述,我们对其他调试工具,其他调试的问题比如检测内存泄露等内容,也会进行说明。此部分内容放于本文档的第三部分。

为什么需要汇编级调试
逆向工程的需要
例子1:NT 内核的进程调度分析笔记 http://www.whitecell.org/list.php?id=11

例子2: NT 下动态切换进程分析笔记 http://www.whitecell.org/list.php?id=13

在windows的世界里,内核源码和具体原理是不公开的。但很多牛人就凭一个破烂调试器阅读反汇编代码就能得到内部真相,可见调试器汇编级调试威力之大。但是在linux是源码公开的情况下,就没必要干那样的辛苦活了。但是因为以下原因,汇编级调试还是必要的。

汇编比C语言更低层
有时(比如代码优化)情况下,因为C代码经过了编译器的处理,调试器在c源码调试这个级别下给出的信息是无法理解的,甚至看起来是错误的。但是如果直接对调试器给出的反汇编代码进行分析,就不会受到那类问题的束缚。也就是说,进行汇编级别的调试能最大程度的利用调试器的功能。

汇编是C语义的解释
当你对某句C语言不是很理解时,看看编译器是怎么想的,是个很不错的办法。

能锻炼汇编源码的阅读能力
另一方面,内核中本来存在很多汇编源代码,进行汇编级调试也是锻炼阅读汇编源码能力的最有效方法

当然,汇编级调试虽然强大,但代价也是很昂贵。和源码级调试相比,分析汇编代码花的时间要多上几十倍。所以,在源码公开的情况下,应该以源码级调试为主,特殊情况下才需要汇编级调试

***第一部分:基础知识***
总纲:内核世界的陷阱
也是阅读理解其他任何大型代码会遇到的问题。下面各节的内容都是围绕这些小项展开的。如果有的内容不知所云,先看后面内容,再回头看这里。

〔先从其他地方复制过来,等待充实〕

源码阅读的陷阱
源码不但是越来越大,更是越来越“刁”了。“刁”到了就是借助源码交叉索引工具也有它索引不到的地方。所以目前,即使是从源码阅读的角度而不是从调试的角度,只利用阅读工具不借助调试工具的话,源码都无法阅读。

源码“刁”到源码解析工具都无法解析的因素有:

1. 汇编源码包括内嵌汇编 可能无法被你的源码阅读工具所解析

2. 汇编代码和C代码之间的调用关系 无法被被源码阅读工具解析

3. 利用函数指针的函数调用 无法被被源码阅读工具解析

4. 宏“假函数” 可能无法被被源码阅读工具解析(SI不能解析,lxr能)

比如page_buffers()。定义是:
#define page_buffers(page)     /
 ({       /
  BUG_ON(!PagePrivate(page));   /
  ((struct buffer_head *)page_private(page)); /
 })
5. 利用宏在编译时动态生成的函数体 无法被被源码阅读工具解析

比如fs/buffer.c中有一大批类似函数。比如buffer_unwritten()
定义在buffer_head.h
 82 #define BUFFER_FNS(bit, name)                                           /
..省略
 91 static inline int buffer_##name(const struct buffer_head *bh)           /
 92 {                                                                       /
 93         return test_bit(BH_##bit, &(bh)->b_state);                      /
 94 }
..
130 BUFFER_FNS(Unwritten, unwritten)
这类函数一般是短小的内嵌函数,用gdb调试时都看不出来。只能靠字符搜索再加上一点机灵。
6. 函数/变量的某类c扩展属性标记, 可能导致该函数/变量无法被被源码阅读工具解析

比如static struct vfsmount *bd_mnt __read_mostly;中的bd_mnt
7. 其他语种的保留关键字,可能无法被你的源码阅读工具所解析

如默认配置的SI无法解析struct class,当然,这个问题和内核无关。
但是借助调试器,就能直接而轻易地解决上述源码解析工具难以解决的问题。

代码调试的陷阱
搭建调试环境

gdb调试器的陷阱

1. 宏“假函数”

2. 内嵌函数

3. 代码优化

4. 汇编码

5. 进程切换

6. 中断处理

7. 系统调用

原理理解的陷阱
0. 链接器脚本和make语法

下面这些杂七杂八的文件对内核整体原理的理解起着决定性的作用。

内核中的链接脚本
linux-2.6$ find ./ -name "*lds*"

内核中的重要宏文件
module_param* macros
include/linux/moduleparam.h

*__initcall Macros
include/linux/init.h

内核中的汇编文件
linux-2.6$ find ./ -name "*.S"

内核中的Makefile
linux-2.6$ find ./ -name "Makefile"

内核中的配置文件
linux-2.6$ find ./ -name "*config*"
1. C与汇编代码的相互调用

2. 各子系统间的接口互动

3. 内核的设计思想及其代码编写和运行形式

a) 基于对象的思想

例子:文件系统,设备模型

b) “发布—订阅”模型

例子:notification chain

建立调试环境
发行版的选择和安装
为什么选debian
〔如题〕 http://www.debian.org/ http://www.emdebian.org/

为什么本人选择debian?因为:引用内容来之www.debian.org

“Debian 计划 是一个致力于创建一个自由操作系统的合作组织。...屁话省略...屁话..N多屁话之后: 当然,人们真正需要的是应用软件,也就是帮助他们完成工作的程序: 从文档编辑,到电子商务,到游戏娱乐,到软件开发。Debian 带来了超过 18733 个 软件包 (为了能在您的机器上轻松的安装,这些软件包都已经被编译包装为一种方便的格式) — 这些全部都是 自由 软件。”

原因终于看到了,选择debian是因为本人比较懒,比较笨。而debian正好迎合了我这种人的需求。

1. 它”带来了超过 18733 个 软件包”。18733这个数目非常不直观,而且或许是N年前的数据了。我们可以到debian的ftp看看,现在它可供安装的软件和工具达到了5个DVD的容量。难以想象,在这5个DVD容量的工具库中,还会找不到我所想要的东西。

2. debian有一个非常出名的安装包管理机制。你需要做的就是,打开“立新得”软件,然后在一个小方框里写上你需要东西的相关信息,然后再点点一个叫做“搜索”的小方块。接着,debian就会在它5个DVD大的工具库中寻找你想要的工具。在结果返回后,选择好你的工具,再点点一个叫做“应用”的小方块,过一会,就可以使用你的工具了。

再也没有了“缺少什么什么包”的烦人提示了,一切都这么简单,又这么强大。这,正是我想要的。

debian与ubuntu
[两者区别,版本外号,支持社区,source list等] 1. ubuntu的易用性比debian要好。尤其是中文支持,还有ubuntu国内有活跃的社区。 2. 虽然ubuntu是基于debian的,apt 软件库也能获取到debian的软件,但它毕竟是不同的系统环境,理念不同,对于一些偏门或太旧或太新的软件时,ubuntu往往不支持,安装不了。比如,gcc-3.4-arm-linux-gnu这个包,发行时间已久,ubuntu下安装不了,但在debian下则可以。http://www.ubuntu.com/community/ubuntustory/debian

如不特别说明,本文档所有命令都是在ubuntu Hardy Heron8.04版本 和debian testing版本下的操作。

从0安装debian
〔如果想领教古典linux相对于windows的特色,请安装一次debian吧。尽管和以前比,已经很智能了。但安装了debian,选了中文环境,发现汉字都是歪歪倒倒的。而且没有汉字输入法,装了汉字输入法后,却用不了。不知道是我笨还是程序有bug.所以不得不用英文写下本烂文,怕把安装过程给忘了。需要翻译回中文〕

How to install and configure a debian system from zero

1.install the system with one CD

Download CD iso file from debian official website, and burn it into a CD. Note that, we can just download the first CD iso but not DVDs or the whole serials of CDs, because the first CD has already contained all the basis components of dedian system and many other most common applications. We can use the first CD to install debian system, and then to install some other needed programs from it if needed. In this way, you can save much time spent on touching many inrelatived things.

2.install application & tool from CD

ou can install some common apllications from the CD with the following commnad: apt-get install expected-application. Why can we do that without any more configuration? Why is it not need to has a ability to access internet? Well, Let’s look at the file named sourse.list which idenifying where to get software’s pakage?? deb cdrom:[Debian GNU/Linux testing _Lenny_ - Official Snapshot i386 CD Binary-1 20080605-15:01]/ lenny main It means that system try to get somethig from your CD, so obviously that you can get some the most common but not all the tools available in debian official apllication repository.

3.try to access the internet

Thank to the first CD, we can do that easily. Fist, install the tool ppp contained in CD and its’ configuration tool pppoeconfig. All these steps are described in file ADSL(PPPOE)接入指南.txt

4.search any useful information through the internet

now, we have built a base debian system, but it is too simple. I want to do some some thing, for example, to chat with some other people with pidgin, but it is not contained in the first CD, which just downloaded by you. And you may want to search some helps with google,etc. Just to do it, google is a most useful tool.

5.search the internet updating source

I think you have get much thing through the google. But the most important thing is to get a available update source for your system, and change the source.list–that is /etc/apt/source.list. Now, I have got a good one, and it seems good. Don’t forget to turn on the security entry in the orgion file source.list. That file looks like following after my updataion:

#deb cdrom:[Debian GNU/Linux testing _Lenny_ - Official Snapshot i386 CD Binary-1 20080605-15:01]/ lenny main
deb http://ftp.debian.org/debian/ lenny main contrib non-free 
deb http://security.debian.org/ lenny/updates main
deb-src http://security.debian.org/ lenny/updates main
You should note that the internet address is debian office’s, but It takes some while to get it. And my searching tool is google. :) Oh, we shoul run a command to update the new configuration to system before using it, don’t ferget: apt-get update

6.get help from IRC

Well, we have already been able to get some applications or tools from internet with command apte-get or wget,etc.. But I think the first thing to do is to get and install a very valuable tool named pidgin which can bring you into IRC world. Because Many experiance and kind person live in channel #debian of irc.freenode.net. You can get help from it very quickly. How to configure pidgin? Sorry, I don’t like to answer such a problem , please just to google it or try it by yourselft. I am not so kind as some guys living in IRC : )

7.get and install synaptic

If you ever used ubuntu, you should agree that synaptic is good tool to update you system. It can save you much time of searching tools, typing commnad, or managing the downloaded tools. But Unfortunately, such a important tool is not installed in the default system, and it is not contained in the first CD. So, We can just to get it with command “apt-get install synaptic”. After doing that successfully, I don’t want to type that command anymore. It’s so tedious to me.

8.get more tools with the help of synaptic

synaptic is my GOD in the linux world. Without it, I will become crazy. But now, I have owned it, so I can fly very freely in the internet sky. Just to search any tools and to update your system. And now, the CD used to install debian can be discarded, if you will never reinstall or rescure the system with it in future.

Now, the sun has raise up, and you have found the road to reback to civilization. Why? Just to ask your google and synaptic. :)

debian重要命令
〔来源〕《APT and Dpkg 快速参考表》http://i18n.linux.net.cn/others/APT_and_Dpkg.php

Apt 不止是 apt-get

http://www.erwinwang.com/node/10

中文环境设置
debian的键盘设置更改
默认安装的debian,键盘的设置可能有问题。比如“|”打不出来。值得一提的是,这个设置甚至是和qemu的monitor模式相关联的。也就是说,qemu下有的字符也打不出来。如果有这个问题,按下面步骤设置

System→Preferences→Keyboard→Layouts

然后通过“Add”增加China,并设置它为默认,或者同时把其他的删除掉。

英文Locale下使用中文输入法
说明,中文环境比英文环境有很多缺点。比如编译时编译器的提示都给汉化了,有如,minicom的中文汉化界面是错乱的,而且minicom无法设置。本人一般是英文环境+中文输入法。先安装好好中文环境,系统中就有了中文输入法和其他一些和中文有关的东西。然后转到英文环境下,按照下面做法更改scim的配置文件即可。

来自:http://wiki.ubuntu.org.cn/index.php?title=%E8%8B%B1%E6%96%87Locale%E4%B8%8B%E4%BD%BF%E7%94%A8%E4%B8%AD%E6%96%87%E8%BE%93%E5%85%A5%E6%B3%95&variant=zh-cn

编辑 /etc/gtk-2.0/gtk.immodules(如果存在的话) 或者 /usr/lib/gtk-2.0/2.10.0/immodule-files.d/libgtk2.0-0.immodules 文件,在xim 的 local 增加 en 也就是说:

"xim" "X Input Method" "gtk20" "/usr/share/locale" "ko:ja:th:zh"
改成:
"xim" "X Input Method" "gtk20" "/usr/share/locale" "en:ko:ja:th:zh"
注意,一定要重启一下机器。
pdf乱码的解决
$sudo apt-get install xpdf-chinese-simplified xpdf-chinese-traditional poppler-data
参考:

http://wiki.ubuntu.org.cn/PDF%E6%96%87%E6%A1%A3%E7%9A%84%E4%B9%B1%E7%A0%81%E9%97%AE%E9%A2%98

建立编译环境
$ sudo apt-get install build-essential autoconf automake1.9 cvs subversion libncurses5-dev git rar unrar p7zip-full cabextract
其余的根据出错的提示,利用“立新得”搜索,然后进行安装。没有“立新得”界面程序的可以在终端下利用以下命令来搜索和安装。

$ sudo apt-get update
$ apt-cache search XXX
$ sudo apt-get install XXX
双硬盘系统切换设置, 私人备忘用

title           Microsoft Windows XP Professional
root            (hd1,0)
savedefault
makeactive
map             (hd0) (hd1)
map             (hd1) (hd0)
chainloader     +1
安装交叉编译工具
交叉编译工具下载网址
下面是几个交叉编译工具下载网址,需要手动安装时,对比一下编译器的名称可以找到合适的下载地址。debian维护有自己的已经打包成.deb形式安装包,在debian软件库中。

http://www.codesourcery.com/gnu_toolchains/arm/download.html
(据说是arm公司推荐的)

Download Sourcery G++ Lite Edition for ARM

Target OS  Download 
EABI          Sourcery G++ Lite 2008q1-126
                All versions...
uClinux  Sourcery G++ Lite 2008q1-152
                All versions...
GNU/Linux  Sourcery G++ Lite 2008q1-126
                All versions...
SymbianOS  Sourcery G++ Lite 2008q1-126
                All versions...

到底是选EABI还是GNU/LINUX呢?应该是后者....

点GNU/LINUX的连接进去,可看到

Download                  MD5 Checksum
IA32 GNU/Linux Installer  93eee13a08dd739811cd9b9b3e2b3212
IA32 Windows Installer         fac5b0cee1d9639c9f15e018e6d272ad

Documentation

Title                    Format
Assembler (PDF)     PDF
Binary Utilities (PDF)   PDF
C Library (GLIBC) (PDF)  PDF
Compiler (PDF)    PDF
Debugger (PDF)    PDF
Getting Started Guide (PDF)  PDF
Linker (PDF)    PDF
Preprocessor (PDF)   PDF
Profiler (PDF)    PDF

Advanced Packages

Expert users may prefer packages in these formats.

Download   MD5 Checksum
IA32 GNU/Linux TAR  4f11b0fa881864f220ab1bd84666108b
IA32 Windows TAR  ed6d25fd68301e728a1fba4cd5cb913f
Source TAR   2db28fb2aa80134e7d34d42b7039d866

   名字标识不是很明显,进去看才知道。比如,IA32 GNU/Linux Installer对应的安装包
名字叫arm-2008q1-126-arm-none-linux-gnueabi.bin
   为什么有个none?迷茫中..
---------------------------------
http://ftp.snapgear.org:9981/pub/snapgear/tools/arm-linux/
[DIR] Parent Directory                30-Sep-2003 15:44      -  
[   ] arm-linux-tools-20031127.tar.gz 26-Nov-2007 16:56   141M  
[   ] arm-linux-tools-20051123.tar.gz 24-Nov-2005 00:50   228M  
[   ] arm-linux-tools-20061213.tar.gz 13-Dec-2006 13:31   230M  
[   ] arm-linux-tools-20070808.tar.gz 30-Nov-2007 03:21   271M  
[   ] binutils-2.16.tar.gz            16-Nov-2005 15:44  15.6M  
[   ] binutils-2.17.tar.gz            06-Dec-2007 10:24  17.4M  
[   ] build-arm-linux-3.4.4           02-Aug-2006 14:32     6k  
[   ] build-arm-linux-4.2.1           30-Jul-2008 10:13     7k  
[   ] elf2flt-20060707.tar.gz         17-Jan-2008 22:23   101k  
[   ] elf2flt-20060708.tar.gz         30-Jul-2008 10:14   110k  
[   ] gcc-3.4.4.tar.bz2               16-Nov-2005 15:39  26.3M  
[   ] gcc-4.2.1.tar.bz2               06-Dec-2007 10:11  42.0M  
[   ] genext2fs-1.3.tar.gz            03-Sep-2003 10:23    19k  
[   ] glibc-2.3.3.tar.gz              16-Nov-2005 15:49  16.7M  
[   ] glibc-2.3.6.tar.gz              06-Dec-2007 10:39  17.9M  
[   ] glibc-linuxthreads-2.3.3.tar.gz 16-Nov-2005 15:49   303k  
[   ] glibc-linuxthreads-2.3.6.tar.gz 06-Dec-2007 10:39   320k  
--------------------------
http://www.handhelds.org/download/projects/toolchain/
[DIR] Parent Directory                                                   -   
[   ] README                                        28-Jul-2004 17:37  788   
[DIR] archive/                                      28-Jul-2004 17:34    -   
[   ] arm-linux-gcc-3.3.2.tar.bz2                   03-Nov-2003 10:23   71M  
[   ] arm-linux-gcc-3.4.1.tar.bz2                   29-Jul-2004 14:01   41M  
[DIR] beta/                                         28-Jul-2004 17:36    -   
[   ] crosstool-0.27-gcc3.4.1.tar.gz                28-Jul-2004 17:21  2.0M  
[   ] gcc-build-cross-3.3                           31-Oct-2003 15:43  5.1K  
[DIR] jacques/                                      24-Jul-2001 18:45    -   
[   ] kernel-headers-sa-2.4.19-rmk6-pxa1-hh5.tar.gz 12-Mar-2003 17:42  4.7M  
[DIR] monmotha/                                     13-Aug-2002 17:54    -   
[DIR] osx/                                          14-Dec-2003 11:45    -   
[DIR] pb/                                           22-Nov-2002 20:10    -   
[DIR] source/                                       18-Mar-2004 16:12    -   
------------------------------------
http://ftp.arm.linux.org.uk/pub/armlinux/toolchain/
[DIR] Parent Directory                                     -   
[   ] Oerlikon-DevKit-XScalev2.tar.gz 07-Feb-2003 22:30  3.7K  
[   ] cross-2.95.3.tar.bz2            20-Jul-2001 21:12   35M  
[   ] cross-3.0.tar.bz2               20-Jul-2001 22:27   39M  
[   ] cross-3.2.tar.bz2               23-Aug-2002 11:04   81M  
[   ] cross-3.2.tar.gz                23-Aug-2002 10:01   93M  
[DIR] src-2.95.3/                     14-Jan-2002 17:52    -   
[DIR] src-3.2/                        23-Aug-2002 10:53    -   
--------------------------------------------
http://linux.omap.com/pub/toolchain/
[DIR] Parent Directory                             -   
[   ] obsolete-gcc-3.3.2.t..> 15-May-2004 12:18   76M  
---------------------------
http://www.uclinux.org/pub/uClinux/arm-elf-tools/
To install the Linux binaries, login as root and run "sh ./XXX-elf-tools-20030314.sh".

m68k-elf-20030314/arm-elf-20030314
    Get the m68k binaries or the ARM binaries. The source is here.

m68k-elf-20020410/arm-elf-20011219
    Get the m68k binaries or the ARM binaries. The source is here.

m68k-elf-20020218/arm-elf-20011219
    Get the m68k binaries or the ARM binaries. The source is here.

m68k/arm-elf-20011219
    Get the m68k binaries or the ARM binaries. The source is here.

    You can also get Bernhard Kuhn's RPMs here.

m68k-elf-20010716
    Get the binaries here and the source from here.

m68k-elf-20010712
    Get the binaries here and the source from here.

m68k-elf-20010610
    Get the binaries here and the source from here.

m68k-elf-20010228
    The binaries are in two files, the compilers and the g++ headers. The source is here. 
安装arm-linux-gnueabi-XXX 工具集
debian有自己维护的一套交叉编译工具集

[参考]http://www.emdebian.org/tools/crosstools.html

工具库: http://www.emdebian.org/debian/pool/main/

步骤:

1. 往/etc/apt/sources.list文件加入下面软件源

deb http://buildd.emdebian.org/debian/ unstable main
deb-src http://buildd.emdebian.org/debian/ unstable main
deb http://buildd.emdebian.org/debian/ testing main
deb-src http://buildd.emdebian.org/debian/ testing main
然后:

安装 emdebian-archive-keyring package 
$ sudo apt-get install emdebian-archive-keyring
更新
$ sudo apt-get update
2. 安装交叉编译器

$ sudo apt-get install libc6-armel-cross libc6-dev-armel-cross binutils-arm-linux-gnueabi gcc-4.3-arm-linux-gnueabi g++-4.3-arm-linux-gnueabi
注意,在ubuntu8.04下,只能安装4.2版。把上面文字中的4.3全部换为4.2即可。

3. 安装交叉调试

$sudo apt-get install gdb-arm-linux-gnueabi
注意:

a. 安装时使用名称:gdb-arm-linux-gnueabi,调用时使用命令名是:arm-linux-gnueabi-gdb

b. ubuntu下,arm-linux-gnueabi-gdb和gdb有冲突。

解决方法

需要使用arm-linux-gnueabi-gdb时先卸载gdb,记下卸载gdb时与gdb一起被卸载的软件名,然后安装arm-linux-gnueabi-gdb。 想换回gdb时,在反操作。apt-install remove arm-linux-gnueabi-gdb 然后 apt-get install gdb以及之前和gdb一起被卸载包。可以写个脚本自动完成这些操作。本人环境下的脚本是:

脚本1. install-armgdb.sh

#! /bin/sh
sudo apt-get remove gdb
sudo apt-get install gdb-arm-linux-gnueabi
脚本2. install-gdb.sh

#! /bin/sh
sudo apt-get remove gdb-arm-linux-gnueabi
sudo apt-get install apport apport-gtk apport-qt bug-buddy cgdb gdb python-apport xxgdb
什么是EABI
答: 来自AAPCS

ABI: Application Binary Interface:

1). The specifications to which an executable must conform in order to execute in a specific execution environment. For example, the Linux ABI for the ARM Architecture.

2). A particular aspect of the specifications to which independently produced relocatable files must conform in order to be statically linkable and executable. For example, the C++ ABI for the ARM Architecture, the Run-time ABI for the ARM Architecture, the C Library ABI for the ARM Architecture.

ARM-based … based on the ARM architecture …

EABI: An ABI suited to the needs of embedded (sometimes called free standing) applications.

参考:

ABI/EABI/OABI http://blog.csdn.net/hongjiujing/archive/2008/07/21/2686556.aspx

Re: 关于kernel ARM_EABI http://zh-kernel.org/pipermail/linux-kernel/2008-January/002793.html

Why ARM’s EABI matters http://www.linuxdevices.com/articles/AT5920399313.html

Why switch to EABI? http://www.applieddata.net/forums/topic.asp?TOPIC_ID=2305

ArmEabiPort http://wiki.debian.org/ArmEabiPort

安装arm-elf-XXX 工具集
注:arm-elf-XXX 工具集是用于uclinux的

1. 依据要求搜索下载相应的arm-elf-tools安装包。比如arm-elf-tools-20030315.sh

2. 安装: $ ./arm-elf-tools-20030315.sh

3. 如果,该安装包年代过老,比如arm-elf-tools-20030315.sh,会出现下面的错误提示 “tail: 无法打开“ 43” 读取数据: 没有那个文件或目录。”。 这时需要修改安装包源码。方法:vi arm-elf-tools-20030315.sh, 搜索tail,在它后面加 -n .比如 把tail ${SKIP} ${SCRIPT} | gunzip | tar xvf -改成如下:tail -n ${SKIP} ${SCRIPT} | gunzip | tar xvf -

4.如何卸载已安装的arm-elf-tools? 答,重新安装一次,注意看终端提示。或直接vi arm-elf-tools-20030315.sh,看脚本的内容,

bin工具集的使用
〔该怎么称呼这类工具?待详述〕

arm-elf-addr2line   arm-elf-elf2flt     arm-elf-gdb         arm-elf-objdump     arm-elf-size
arm-elf-ar          arm-elf-flthdr      arm-elf-ld          arm-elf-protoize    arm-elf-strings
arm-elf-as          arm-elf-g++         arm-elf-ld.real     arm-elf-ranlib      arm-elf-strip
arm-elf-c++         arm-elf-gasp        arm-elf-nm          arm-elf-readelf     arm-elf-unprotoize
arm-elf-c++filt     arm-elf-gcc         arm-elf-objcopy     arm-elf-run 

arm-linux-gnueabi-addr2line  arm-linux-gnueabi-g++        arm-linux-gnueabi-gprof      arm-linux-gnueabi-readelf
arm-linux-gnueabi-ar         arm-linux-gnueabi-g++-4.2    arm-linux-gnueabi-ld         arm-linux-gnueabi-size
arm-linux-gnueabi-as         arm-linux-gnueabi-gcc        arm-linux-gnueabi-nm         arm-linux-gnueabi-strings
arm-linux-gnueabi-c++filt    arm-linux-gnueabi-gcc-4.2    arm-linux-gnueabi-objcopy    arm-linux-gnueabi-strip
arm-linux-gnueabi-cpp        arm-linux-gnueabi-gdb        arm-linux-gnueabi-objdump    
arm-linux-gnueabi-cpp-4.2    arm-linux-gnueabi-gdbtui     arm-linux-gnueabi-ranlib      
如何获取这些工具的命令选项? 看章节“知识从哪里来” 一般是用命 xxxxxx –help就能得到简单的命令选项列表

下载arm-linux-gnueabi- 手册地址http://www.codesourcery.com/gnu_toolchains/arm/portal/release324

然后搜索”arm”,便能找到处理器相关的特殊命令选项

arm-linux-gnueabi-gcc
查看arm处理器相关的编译选项

$ vi arch/arm/Makefile

阅读Makefile文件,并联系源码根目录下的.config文件,便能知道arm-linux-gnueabi-gcc用了哪些编译选项。再到手册中查找,便能知道这些选项是干什么用的,但手册中说的不是很详细。另外查找有用解释的方法的是,利用make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- menuconfig,找到与命令选项有关联的CONFIG_XXX的菜单项,看它的帮助说明.比如

$ vi arch/arm/Makefile
....
ifeq ($(CONFIG_AEABI),y)
CFLAGS_ABI      :=-mabi=aapcs-linux -mno-thumb-interwork
else
CFLAGS_ABI      :=$(call cc-option,-mapcs-32,-mabi=apcs-gnu) $(call cc-option,-mno-thumb-interwork,)
endif
.. 
再查看CONFIG_AEABI的帮助文档 $ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- menuconfig 找到CONFIG_AEABI相关的菜单,看它的帮助文档,便能知道选项-mabi=aapcs-linux -mno-thumb-interwork的整体效果怎样的。

  ┌————————————————————— Use the ARM EABI to compile the kernel ——————————————————————┐
  │ CONFIG_AEABI:                                                                     │  
  │                                                                                   │  
  │ This option allows for the kernel to be compiled using the latest                 │  
  │ ARM ABI (aka EABI).  This is only useful if you are using a user                  │  
  │ space environment that is also compiled with EABI.                                │  
  │                                                                                   │  
  │ Since there are major incompatibilities between the legacy ABI and                │  
  │ EABI, especially with regard to structure member alignment, this                  │  
  │ option also changes the kernel syscall calling convention to                      │  
  │ disambiguate both ABIs and allow for backward compatibility support               │  
  │ (selected with CONFIG_OABI_COMPAT).                                               │  
  │                                                                                   │  
  │ To use this you need GCC version 4.0.0 or later.                                  │  
  │                                                                                   │  
  │ Symbol: AEABI [=n]                                                                │  
  │ Prompt: Use the ARM EABI to compile the kernel                                    │  
  │   Defined at arch/arm/Kconfig:554                                                 │  
  │   Location:                                                                       │  
  │     -> Kernel Features     

arm-linux-gnueabi-gcc的主要编译选项有如下几个。但是在编译内核时,这些选项是不需要手工去写的,而是通过make menuconfig生成包含了编译选项配置信息的.config文件。在make编译内核时,再利用Makefile文件中的规则结合.config文件提取出那些选项。

太多了,手册吧
arm-linux-gnueabi-gdb
注意它的默认选项设置

$ arm-linux-gnueabi-gdb
(gdb) show arm
abi:  The current ARM ABI is "auto" (currently "APCS").
apcs32:  Usage of ARM 32-bit mode is on.
disassembler:  The disassembly style is "std".
fpu:  The current ARM floating point model is "auto" (currently "fpa").
(gdb) 
但是,如果如果在命令后有参数vmlinux的话,它会自动识别出内核的abi,从而自动设置了gdb的abi。比如,在编译内核时,如果选了CONFIG_AEABI,则gdb的提示如下

$ arm-linux-gnueabi-gdb vmlinux 
...
(gdb) show arm
abi:  The current ARM ABI is "auto" (currently "AAPCS").  <--注意
apcs32:  Usage of ARM 32-bit mode is on.
disassembler:  The disassembly style is "std".
fpu:  The current ARM floating point model is "auto" (currently "softvfp").
qemu的使用
参考手册

http://bellard.org/qemu/user-doc.html

http://wiki.debian.org.tw/index.php/QEMU

http://www.h7.dion.ne.jp/~qemu-win/

http://bellard.org/qemu/

邮件列表

http://lists.gnu.org/archive/html/qemu-devel/

参考文章

“QEMU安装使用全攻略” http://forum.ubuntu.org.cn/viewtopic.php?p=248267&sid=f4e95025bdaf6a24a218315d03ad9933

〔补充命令〕引用自http://bbs.chinaunix.net/viewthread.php?tid=779540

安装过程中,要求换盘:
在qemu中按ctrl+alt+2切换到qemu monitor模式 输入?或help可以查看可用命令及使用说明。
(在其他版本的qemu中,运行qemu加载OS后,这个shell就会自动变成qemu monitor模式)
change device filename -- change a removable media
看来它就是用来换盘的了 : change cdrom /rhel4/EL_disc2.iso

切换回安装界面ctrl+alt+1

monitor下还有几个常用的命令:
savevm filename 将整个虚拟机当前状态保存起来
loadvm filename 恢复 (最初我没用change换盘时,就是先savevm->重新运行qemu->loadvm )
sendkey keys 向VM中发送按键,例如你想在虚拟机里切换到另一个终端,按下了ctrl-alt-F2
不幸的是,切换的却是你的主系统,所以就需要用 sendkey了 sendkey ctrl-alt-f2
还有其他几个命令,自己看看啦。

经过N久终于装好了,现在可以启动试试:
[root@LFS distro]#qemu redhat.img -enable-audio -user-net -m 64
-user-net 相当于VMware的nat,主系统可以上,虚拟机就可以
-m 64     使用64M内存,缺省下使用128M

ctrl-alt-f 全屏
ctrl-alt   主机/虚拟机鼠标切换
qemu还有一些其他参数,输入qemu可以查看其相关说明
initrd.img的原理与制作
〔扩展,原理,相关命令。下面的skyeye可能需要这部分知识〕

Linux2.6 内核的 Initrd 机制解析” http://www.ibm.com/developerworks/cn/linux/l-k26initrd/

“Introducing initramfs, a new model for initial RAM disks”http://www.linuxdevices.com/articles/AT4017834659.html

””深入理解 Linux 2.6 的 initramfs 机制 (上)“http://blog.linux.org.tw/~jserv/archives/001954.html

MKINITRAMFS http://www.manpage.org/cgi-bin/man/man2html?8+mkinitramfs

安装与使用
$ sudo apt-get install initramfs-tools 
$ mkinitramfs /lib/modules/2.6.26/ -o initrd.img-2.6.26
x86虚拟调试环境的建立
参考

“debugging-linux-kernel-without-kgdb”http://memyselfandtaco.blogspot.com/2008/06/debugging-linux-kernel-without-kgdb.html

“使用 KGDB 调试 Linux 内核” http://blog.chinaunix.net/u/8057/showart_1087126.html

“透过虚拟化技术体验 kgdb (1)” http://blog.linux.org.tw/~jserv/archives/002045.html

基于qemu和内核内置kgdb
缺点:相对于下节的“基于qemu和qemu内置gdbstub”,这个方法配置麻烦。

优点:真机远程调试时只能使用内置kgdb这个方法

〔等待扩展,,,,〕

终极参考

“Using kgdb and the kgdb Internals”http://www.kernel.org/pub/linux/kernel/people/jwessel/kgdb/index.html

参考文章

“使用 KGDB 调试 Linux 内核” http://blog.chinaunix.net/u/8057/showart_1087126.html

基于qemu和qemu内置gdbstub
参考文章
“Debugging Linux Kernel Without KGDB Patch (Qemu + GDB)”http://memyselfandtaco.blogspot.com/2008/06/debugging-linux-kernel-without-kgdb.html

优缺点
优点:相对上节,优点是操作简单,几乎不需要什么配置

缺点:真机的远程调试,就只能利用内核的内置kgdb了

说明:

如果长时间调试固定版本的内核,采取下面的把调试用内核安装的虚拟机内部就可以了。但是如果是要频繁地更换新内核或修改被调试内核,就需要采取把内核挂在虚拟机外部的形式。也就是用 -kernel 在虚拟机外面挂个内核, 再利用-append 传递起内核启动参数等。〔待研究〕

〔太概过了,待扩展...〕

调试用内核的安装过程:
1. 利用qemu安装一个系统.

2. 在真机中配置并编译一个用于安装到虚拟系统中的新内核,注意配置时的选择

* 配置和启动
1. 内核选项
同时,为了能在系统运行时中断系统并出发远程 gdb,必须打开内核 Magic Sys-Rq 键选项 :[后记,没实验去掉会怎样,估计没影响]
CONFIG_MAGIC_SYSRQ=y
打开内核符号调试
CONFIG_DEBUG_INFO=y
3. 在真机下编译好虚拟机新内核的源码

4. 结束qemu,用以下命令在真机上挂载虚拟硬盘。然后把编译好的整个源码目录都拷贝到挂载好的虚拟硬盘上(真机上保留一份源码)。

$ sudo mount -o loop,offset=32256 debian.img /mnt
拷贝完后,在真机上卸载虚拟硬盘

$ sudo umount /mnt
5.启动虚拟机,进入旧系统,在新内核源码根目录下用以下命令给qemu的虚拟系统安装一个新的内核

拷贝模块
$ make modules_install
安装内核

$ make install
制作initrd.img
$ cd /boot
$ mkinitramfs /lib/modules/2.6.26/ -o initrd.img-2.6.26
检查/boot/grub/menu.lst 文件内容是否妥当
6.用以下命令重启虚拟系统,并选择进入新系统,确认新系统是否安装成功。

$ shutdown -r now
调试
1. 在真机新内核源码目录下建立一个文件 .gdbinit 内容是

target remote localhost:1234
b start_kernel
#c
注意我把c注释掉是因为ddd和gdb有切换的需要。见”gdb技巧”

2. 用以下命令启动虚拟机

qemu -hda debian.img -cdrom ../debian-testing-i386-CD-1.iso -m 500 -S -s
3. 在真机新内核源码目录下运行

gdb ./vmlinux
[实验记录]

实验过了,.config中不选择kgdb,利用qemu照样能调试。也不能调试start_kernel以前的代码。比如head_32.S中的代码。

CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
但是不知CONFIG_HAVE_ARCH_KGDB是在menuconfig菜单的哪里。想试试把这项去了qemu还能不能调试

经测试,取消CONFIG_HAVE_ARCH_KGDB后,qemu也能进行调试。情况不变。看来qemu能完全脱离内核中的kgdb就能调试内核。

调试截图
步骤2:
XXX@ubuntu:/new/myqemu/debian-x86$ qemu -hda debian.img -cdrom ../debian-testing-i386-CD-1.iso -m 500 -S -s

步骤3:
由下图我们注意到:“基于qemu和qemu内置gdbstub”这个方法调试,最早只能从函数 start_kernel () 开始进行。
内核在start_kernel ()之前的初始化过程就无法观察了。这就是这个方法的最大缺点。但下节利用skyeye调试arm-linux
方法就可以从第一个机器指令开始进行。

XXX@ubuntu:/storage/myqemu/new/linux-2.6.26$ gdb ./vmlinux 
GNU gdb 6.8-debian
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
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 "i486-linux-gnu"...
0x0000fff0 in ?? ()
Breakpoint 1 at 0xc037f5ca: file init/main.c, line 535.
(gdb) c
Continuing.

Breakpoint 1, start_kernel () at init/main.c:535
535 {
(gdb)

调试示意图:
给sys_read下断点
(gdb) b sys_read
Breakpoint 2 at 0xc017585e: file fs/read_write.c, line 360.
(gdb)

用快捷键 ctrl+x+2 打开tui,并按c继续运行,而后拦截到sys_read
   ┌——fs/read_write.c————————————————————————————————————————————————————————————————————————————————————————————————————————┐
   │354     {                                                                                                                │
   │355             struct file *file;                                                                                       │
   │356             ssize_t ret = -EBADF;                                                                                    │
   │357             int fput_needed;                                                                                         │
   │358                                                                                                                      │
   │359             file = fget_light(fd, &fput_needed);                                                                     │
B+>│360             if (file) {                                                                                              │
   │361                     loff_t pos = file_pos_read(file);                                                                │
   │362                     ret = vfs_read(file, buf, count, &pos);                                                          │
   │363                     file_pos_write(file, pos);                                                                       │
   │364                     fput_light(file, fput_needed);                                                                   │
   │365             }                                                                                                        │
   │366                                                                                                                      │
   │367             return ret;                                                                                              │
   ┌—————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————┐
   │0xc017585a            push   %ebp                                                                              │
   │0xc017585b          mov    %esp,%ebp                                                                         │
   │0xc017585d          push   %esi                                                                              │
B+>│0xc017585e          mov    $0xfffffff7,%esi                                                                  │
   │0xc0175863          push   %ebx                                                                              │
   │0xc0175864         sub    $0xc,%esp                                                                         │
   │0xc0175867         mov    0x8(%ebp),%eax                                                                    │
   │0xc017586a         lea    -0xc(%ebp),%edx                                                                   │
   │0xc017586d         call   0xc0175f65                                                            │
   │0xc0175872         test   %eax,%eax                                                                         │
   │0xc0175874         mov    %eax,%ebx                                                                         │
   │0xc0175876         je     0xc01758b1                                                           │
   │0xc0175878         mov    0x24(%ebx),%edx                                                                   │
   │0xc017587b         mov    0x20(%eax),%eax                                                                   │
   └—————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————┘
remote Thread 42000 In: sys_read                                                                    Line: 360  PC: 0xc017585e 
(gdb) c
Continuing.

Breakpoint 2, sys_read (fd=3, buf=0xbfc781a4 "", count=512) at fs/read_write.c:360
(gdb) 
arm虚拟调试环境的建立
利用qemu
利用qemu安装debian linux
目标:

本节在qemu虚拟机上安装一个基于arm的“桌面“系统,可以有X桌面,该虚拟系统能利用apt-get从debian的软件库下载数不完的用交叉编译已经编译好的arm下的程序和工具。除了虚拟处理器是arm外,简直就是PC机。可以进行应用程序的本机(在虚拟机内进行)调试。但是,本人装的时候,如果选了安装桌面环境,内核就启动失败,好像是提示文件系统出错。〔成功的麻烦把过程贴出来〕

过程是:

Debian on an emulated ARM machinehttp://www.aurel32.net/info/debian_arm_qemu.php

下面是过程的提炼步骤,方便查看。

1.创建虚拟硬盘

$ qemu-img create -f qcow hda.img 40G

2.下载必要文件

$ wget http://people.debian.org/~aurel32/arm-versatile/vmlinuz-2.6.18-6-versatile
$ wget http://people.debian.org/~aurel32/arm-versatile/initrd.img-2.6.18-6-versatile 
$ wget http://ftp.de.debian.org/debian/dists/etch/main/installer-arm/current/images/rpc/netboot/initrd.gz 
2.安装系统

qemu-system-arm -M versatilepb -kernel vmlinuz-2.6.18-6-versatile -initrd initrd.gz -hda hda.img -append "root=/dev/ram" 
在安装过程中,为了节省时间,在这步choose a mirror of the debian archive
选http 回车 ;
debian archive mirror country 选taiwan 回车; 
debian archive mirror 选ftp.tw.debian.org

安装好基本系统后,不要选择安装Desktop environment

安装完成后,它提示你把光盘拿掉并重启系统时,终止掉qemu。并用下一步的命令启动qemu.不要回车,否则又重新安装。
3. 第一次启动系统

$ qemu-system-arm -M versatilepb -kernel vmlinuz-2.6.18-6-versatile -initrd initrd.img-2.6.18-6-versatile -hda hda.img -append "root=/dev/sda1"
4. 把旧的内核,intrd.img制作工具安装到虚拟机的系统内(操作在虚拟机内)

$ apt-get install initramfs-tools
$ wget http://people.debian.org/~aurel32/arm-versatile/linux-image-2.6.18-6-versatile_2.6.18.dfsg.1-18etch1+versatile_arm.deb
$ su -c "dpkg -i linux-image-2.6.18-6-versatile_2.6.18.dfsg.1-18etch1+versatile_arm.deb" 
5.其他更多的玩法请看原文http://www.aurel32.net/info/debian_arm_qemu.php

参考:

Debian ARM Linux on Qemu

http://909ers.apl.washington.edu/~dushaw/ARM/#SYSTEM

Running Linux for ARM processors under QEMU

http://iomem.com/index.php?archives/2-Running-Linux-for-ARM-processors-under-QEMU.html&serendipity[entrypage]=2

Debian on an emulated ARM machine

http://www.aurel32.net/info/debian_arm_qemu.php

利用qemu安装能进行内核调试的系统
〔暂时没法子,期待扩展。下面这个例子可以,但没尝试。估计这个方法与下节的利用skyeye的方法相比,没有优势。因为这个方法可能也是不能进行全程调试。但是下面网站的资料还是有一定参考价值的。〕

使用qemu-jk2410做为学习环境:

http://wiki.jk2410.org/wiki/%E4%BD%BF%E7%94%A8qemu-jk2410%E5%81%9A%E7%82%BA%E5%AD%B8%E7%BF%92%E7%92%B0%E5%A2%83

另外:看看下面这个站点,

Firmware Linux: http://landley.net/code/firmware/

利用skyeye
skyeye虚拟机的内核调试
相对于利用qemu的方式,用skyeye虚拟机调试内核有个很重要的

优点是:

调试可以从第一条机器指令开始。这对研究系统启动过程提供了极大的便利。

skyeye的安装与使用
该文非常好,好像没啥要扩充的

SkyEye硬件模拟平台,第二部分: 安装与使用

http://www.ibm.com/developerworks/cn/linux/l-skyeye/part2/

SkyEye User Manual http://www.skyeye.org/wiki/UserManual

http://skyeye.wiki.sourceforge.net/

参考文档:

Linux-2.6.20 on XXX platform

http://skyeye.wiki.sourceforge.net/Linux

uClinux-dist-20070130 on XXX platform

http://skyeye.wiki.sourceforge.net/uClinux

http://www.linuxfans.org/bbs/thread-182101-1-1.html

安装:

1. 安装主程序

在ubuntu系统能进行在线安装,但版本是v1.2,不是最新的

$sudo apt-get install skyeye
2. 测试套件

测试套件下载后解压开即可

地址:http://sourceforge.net/project/showfiles.php?group_id=85554

快速试玩
目的:

尽可能快的成功运行一个arm linux虚拟机。如果您化了很长时间也无法编译出一个能运行的内核,或写不出一个恰当的skyeye.conf时,在你的热情受到打击之前,我想这节是你急需的。

操作步骤:

1.依照上节说明安装好主程序,下载并解压好测试套件

2.进入测试套件的目录 skyeye-testsuite-1.2.5/linux/s3c2410/s3c2410x-2.6.14

可以看到有三个文件initrd.img skyeye.conf vmlinux

3.运行虚拟机

$skyeye -e vmlinux

注意下面的提示,说明平时要注意在启动命令前加上sudo

NOTICE: you should be root at first !!!
NOTICE: you should inmod linux kernel net driver tun.o!!!
NOTICE: if you don't make device node, you should do commands:
NOTICE:    mkdir /dev/net; mknod /dev/net/tun c 10 200
NOTICE: now the net simulation function can not support!!!
NOTICE: Please read SkyEye.README and try again!!!
4.可以看到,一个2.6.14 版本的linux跑起来了,还带有一个lcd.

快速配置能调试的环境
参考:

http://skyeye.wiki.sourceforge.net/linux_2_6_17_lubbock

环境条件:

1. ubuntu hardy 8.04

2. 安装了debian提供的交叉编译工具套件 arm-linux-gnueabi- (4.2版本)

目标:

这小节能得到基于pxa平台(类似s3c2410,也基于arm核心)的linux2.6.20内核的虚拟系统,具备调试功能。相比“基于qemu和qemu内置gdbstub”该节,利用skyeye的调试有那节所没有的优点:调试时可以从内核运行的第一条指令开始〔这就是模拟硬件调试?〕。

参考手册:

XScale PXA250开发手册 http://soft.laogu.com/download/intelpxa250.pdf

ARMv5 体系结构参考手册 http://www.arm.com/community/university/eulaarmarm.html

操作步骤:

1. 下载linux-2.6.20 (由于交叉编译器太新,如果利用linux-2.6.17则编译不过)

2. 修改文件include/asm-arm/arch-pxa/memory.h 第18行

#define PHYS_OFFSET UL(0xa0000000)

#define PHYS_OFFSET UL(0xc0000000)
3. 下载内核配置选项,放置于linux-2.6.20源码的根目录下http://skyeye.wiki.sourceforge.net/space/showimage/skyeye_2.6.17_lubbock.config

这个下载好的配置文件已经帮我们做了的两件事

首先,在block device菜单下配置了ramdisk和initrd的支持

其次,把内核原来的启动参数改为

root=/dev/ram0 console=ttyS0 initrd=0xc0800000,0x00800000 rw mem=64M
4. 把下载到的skyeye_2.6.17_lubbock.config更名为.config

5. 编译内核

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi-
6. 创建文件 skyeye.conf,内容如下:

cpu: pxa25x
mach: pxa_lubbock
mem_bank: map=I, type=RW, addr=0x40000000, size=0x0c000000
mem_bank: map=M, type=RW, addr=0xc0000000, size=0x00800000
mem_bank: map=M, type=RW, addr=0xc0800000, size=0x00800000, file=./initrd.img
mem_bank: map=M, type=RW, addr=0xc1000000, size=0x00800000
mem_bank: map=M, type=RW, addr=0xc1800000, size=0x02800000
7. 从skyeye的测试套件中拷贝initrd.img到linux-2.6.20源码根目录下。该initrd.img的路径是:

skyeye-testsuite-1.2.5/linux/pxa/2.6.x/
8. 运行内核看看,在linux-2.6.20源码根目录下运行下面的命令。可以看到,内核成功运行

sudo skyeye -e vmlinux
调试

1. 在linux-2.6.20源码根目录下运行命令:

sudo skyeye -d -e vmlinux  
2. 在源码根目录下新开一个终端,并运行:

arm-linux-gnueabi-gdb ./vmlinux
gdb界面出来后

(gdb) target remote:12345
之后可以看到,下断点,查看汇编等一切调试功能和x86下都一样。

3. ddd下如何调用arm-linux-gnueabi-gdb ? 答

$ ddd --debugger arm-linux-gnueabi-gdb ./vmlinux
为s3c2410配置2.6.26内核
〔启动过程中有若干错误提示,但内核能启动成功并运行。有待研究〕

目标:

得到一个基于s3c2410cpu的2.6.26最新稳定内核的虚拟系统,能进行全程的内核调试,即调试能从第一条机器指令开始进行。

参考:

http://skyeye.wiki.sourceforge.net/Linux

http://www.linuxfans.org/bbs/thread-182101-1-1.html

环境条件:

1. ubuntu hardy 8.04

2. 安装了debian提供的交叉编译工具套件 arm-linux-gnueabi- (4.2版本)

操作步骤:

1.依据“安装交叉编译工具”这节,安装好交叉编译工具

2.修改源码

将include/asm-arm/arch-s3c2410/map.h里的
#define S3C2410_CS6 (0x30000000)
改为
#define S3C2410_CS6 (0xc0000000)

将include/asm-arm/arch-s3c2410/memory.h里的
#define PHYS_OFFSET UL(0x30000000)
改为
#define PHYS_OFFSET UL(0xc0000000)
3.把默认.config替换为s3c2410版本

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- s3c2410_defconfig
3.修改配置文件

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- menuconfig
进入[Device Driver] ->[ Character Driver] -> [Serial Driver] 等菜单下 ,
取消8250/16550 and compatible serial support的选择
4.修改内核启动命令

在Boot option --> Default kernel command string 里输入
mem=32M console=ttySAC0 root=/dev/ram initrd=0xc0800000,0x00800000 ramdisk_size=2048 rw
5.编译

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi-
6.从skyeye的测试套件中拷贝相应的文件initrd.img和skyeye.conf到linux-2.6.26源码根目录下。这两个文件的位于

skyeye-testsuite-1.25/linux/s3c2410/s3c2410x-2.6.14/中
7.启动虚拟机

XXX@ubuntu:~/dt/linux-2.6.26$ sudo skyeye -e vmlinux
8.启动完成后那激动人心的logo如下

Welcome to
     _      _____      __   __    _      _
    / /    /  __ /    /  /_/  /  | |    |_|                 
   / _ /   | |  | |  / //   // / | |     _ ____  _   _  _  _ 
  / /_/ /  | |__| | / /  /_/  / /| |    | |  _ /| | | |/ // /
 / /___/ / | |__/ / | |       | || |___ | | |_| | |_| |/    /
/_/  /_/| |   /_/|_|       |_||_____||_|_| |_|/____|/_//_/
    
ARMLinux for Skyeye 
For further information please check:
http://www.skyeye.org/

 

BusyBox v1.4.1 (2007-02-10 01:19:06 CST) Built-in shell (ash)
Enter 'help' for a list of built-in commands.

/bin/ash: can't access tty; job control turned off
/ $ uname -a
Linux skyeye 2.6.26 #2 Sun Oct 5 19:56:57 CST 2008 armv4tl unknown
/ $ 
调试

1. 在linux-2.6.26源码根目录下新建文件”.gdbinit”,内容是:

(gdb) target remote:12345
2. 在linux-2.6.26源码根目录下命令:

sudo skyeye -d -e vmlinux  
3. 在源码根目录下新开一个终端,并运行:

arm-linux-gnueabi-gdb ./vmlinux
之后可以看到,下断点,查看汇编等一切调试功能和x86下都一样。

4. ddd下如何调用arm-linux-gnueabi-gdb ? 答

$ ddd --debugger arm-linux-gnueabi-gdb ./vmlinux
截图:

步骤2:
XXX@ubuntu:~/桌面/test/linux-2.6.26_s3c2410$ sudo skyeye -d -e vmlinux 
big_endian is false.
arch: arm
cpu info: armv4, arm920t, 41009200, ff00fff0, 2 
mach info: name s3c2410x, mach_init addr 0x805f030
lcd_mod:1
dbct info: Note: DBCT not compiled in. This option will be ignored
uart_mod:0, desc_in:, desc_out:, converter:
SKYEYE: use arm920t mmu ops
Loaded RAM   ./initrd.img
start addr is set to 0xc0008000 by exec file.
debugmode= 1, filename = skyeye.conf, server TCP port is 12345
------------------------
步骤3:
fqh@ubuntu:~/桌面/test/linux-2.6.26_s3c2410$ arm-linux-gnueabi-gdb vmlinux
GNU gdb 6.8-debian
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
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 "--host=i486-linux-gnu --target=arm-linux-gnueabi"...
stext () at arch/arm/kernel/head.S:80
80  msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE @ ensure svc mode
Current language:  auto; currently asm
(gdb) source extendinstr //载入辅助的gdb宏
--------------
用快捷键 ctrl+x+2 打开tui模式后的图示,可看到调试是从第一条指令开始的。这对研究系统启动过程提供了极大的便利。
   ┌——arch/arm/kernel/head.S————————————————————————————————————————————————————————————————————————————┐
  >│80              msr     cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE @ ensure svc mode                 │
   │81                                                      @ and irqs disabled                         │
   │82              mrc     p15, 0, r9, c0, c0              @ get processor id                          │
   │83              bl      __lookup_processor_type         @ r5=procinfo r9=cpuid                      │
   │84              movs    r10, r5                         @ invalid processor (r5=0)?                 │
   │85              beq     __error_p                       @ yes, error 'p'                            │
   │86              bl      __lookup_machine_type           @ r5=machinfo                               │
   │87              movs    r8, r5                          @ invalid machine (r5=0)?                   │
   │88              beq     __error_a                       @ yes, error 'a'                            │
   │89              bl      __vet_atags                                                                 │
   │90              bl      __create_page_tables                                                        │
   └————————————————————————————————————————————————————————————————————————————————————————————————————┘
  >│0xc0008000       msr    CPSR_c, #211    ; 0xd3                                               │
   │0xc0008004     mrc    15, 0, r9, cr0, cr0, {0}                                             │
   │0xc0008008     bl     0xc00082f8 <__lookup_processor_type>                                 │
   │0xc000800c    movs   r10, r5                                                              │
   │0xc0008010    beq    0xc0008190 <__error_p>                                               │
   │0xc0008014    bl     0xc0008358 <__lookup_machine_type>                                   │
   │0xc0008018    movs   r8, r5                                                               │
   │0xc000801c    beq    0xc00081e8 <__error_a>                                               │
   │0xc0008020    bl     0xc00083a0 <__vet_atags>                                             │
   │0xc0008024    bl     0xc0008078 <__create_page_tables>                                    │
   │0xc0008028    ldr    sp, [pc, #240]  ; 0xc0008120 <__switch_data>                         │
   └————————————————————————————————————————————————————————————————————————————————————————————————————┘
remote Thread 42000 In: stext                                                  Line: 80   PC: 0xc0008000 
(gdb) b sys_read  //下断点
Breakpoint 1 at 0xc008cc4c: file fs/read_write.c, line 354.
(gdb) c

----------------
调试示意图
效果可能与你机器上看到的不一样。这个例子中,每个gdb单步指令都会自动显示backtrace。这是因为本人使用了章节“gdb宏”中的extendinstr宏。
   ┌——include/asm/thread_info.h——————————————————————————————————————————————————————————————————————————————————————————————┐
   │91       */                                                                                                              │
   │92      static inline struct thread_info *current_thread_info(void) __attribute_const__;                                 │
   │93                                                                                                                       │
   │94      static inline struct thread_info *current_thread_info(void)                                                      │
   │95      {                                                                                                                │
   │96              register unsigned long sp asm ("sp");                                                                    │
  >│97              return (struct thread_info *)(sp & ~(THREAD_SIZE - 1));                                                  │
   │98    &

你可能感兴趣的:(内核编程)