概述
目录[-]
· 大海里的鱼有很多,而我们需要的是鱼钩一只
· 一些前言
· 作者前言
· 知识从哪里来
· 为什么撰写本文档
· 为什么需要汇编级调试
· ***第一部分:基础知识***
· 总纲:内核世界的陷阱
· 源码阅读的陷阱
· 代码调试的陷阱
· 原理理解的陷阱
· 建立调试环境
· 发行版的选择和安装
· 为什么选debian
· debian与ubuntu
· 从0安装debian
· debian重要命令
· 中文环境设置
· debian的键盘设置更改
· 英文Locale下使用中文输入法
· pdf乱码的解决
· 建立编译环境
· 安装交叉编译工具
· 交叉编译工具下载网址
· 安装arm-linux-gnueabi-XXX 工具集
· 什么是EABI
· 安装arm-elf-XXX 工具集
· bin工具集的使用
· arm-linux-gnueabi-gcc
· arm-linux-gnueabi-gdb
· qemu的使用
· initrd.img的原理与制作
· 安装与使用
· x86虚拟调试环境的建立
· 基于qemu和内核内置kgdb
· 基于qemu和qemu内置gdbstub
· arm虚拟调试环境的建立
· 利用qemu
· 利用qemu安装debian linux
· 利用qemu安装能进行内核调试的系统
· 利用skyeye
· skyeye虚拟机的内核调试
· skyeye的安装与使用
· 快速试玩
· 快速配置能调试的环境
· 为s3c2410配置2.6.26内核
· 使用最新的skyeye
· arm开发板调试环境的建立
· 基于串口
· 基于网口
· gdb基础
· 基本命令
· gdb之gui
· gdb技巧
· gdb宏
· 参考资料
· gdb宏的使用
· 实例
· 链表遍历类
· 功能增强类
· 汇编基础--X86篇
· 用户手册
· AT&T汇编格式
· 内联汇编
· 汇编与C函数的相互调用
· 调用链形成和参数传递
· 寄存器的角色与保护
· 调用链的形成
· 栈帧结构与参数传递
· 完整的调用过程
· 调用链回溯的代码实现
· C难点的汇编解释
· 例1
· 例2
· 例3
· 例4
· 优化级别的影响
· 优化选项
· 例子
· 汇编基础--ARM篇
· 用户手册
· 调用链形成和参数传递
· 壮观的标准
· 别名的烦恼
· 寄存器的角色与保护
· 条件执行
· 调用链的形成
· 栈帧结构与参数传递
· 完整的调用过程
· 调用链回溯的实现
· 源码浏览工具
· 调用图生成工具
· find + grep
· wine + SI
· 优缺点
· 安装wine
· 安装SI
· SI的设置
· SI的使用
· global
· Source-Navigator
· vim + cscope/ctags
· 优缺点
· 安装cscope/ctags
· 命令选项
· 使用
· 建立索引
· 利用vim浏览源码
· 快捷键的使用
· kscope
· lxr
· SI等与gdb的特点
· 调用链、调用树和调用图
· 理想调用链
· 函数指针调用
· 调用链的层次
· 非理想调用链
· 调用树与调用图
· 调用树的定义
· 调用树的作用
· 调用树的分类
· 调用树的显示
· 调用树的拼接
· 调用图
· 穿越盲区
· 穿越gdb的盲区
· 进程切换
· 中断异常
· 系统调用
· 穿越交叉索引工具的盲区
· 函数指针
· 查看函数的参数
· 工程方法
· 二叉断点
· 给调用指令下断点
· 绕过时钟中断的干扰
· bug 与 OOPS
· 网站
· ***第二部分:内核分析***
· 调试相关子系统
· kgdb源码分析
· sysrq
· oprofile
· kprobes
· 驱动分析
· 载入模块符号
· seq_file.c的分析
· module.c的分析
· 中断处理过程
· s3c24xx内存初始化分析
· 虚拟地址空间
· 用户层的观察窗
· 交互,从内核层分析
· 理解设备模型
· 面向对象的实现
· 设备模型的分层
· 外围支持机制
· sysfs
· hotplug
· 文件系统
· ***第三部分:其他工具***
· strace
· ltrace
· SystemTap
· MEMWATCH
· YAMD
· Magic SysRq
· 附录:社区交流相关
· 补丁提交相关文档
· 补丁制作与提交示范
· 多补丁发送工具
· git使用
· 附录:内核参考书籍文章
· 内核git库
· 书籍
· 子系统官方网站
· 参考文章
· 私人备忘
大海里的鱼有很多,而我们需要的是鱼钩一只
本文档由大家一起自由编写,修改和扩充,sniper负责维护。引用外来的文章要注明作者和来处。本文档所有命令都是在ubuntu/debian下的操 作。选取的内核源码从文档开始编写时最新的内核版本–2.6.26开始,而且会随着linux的更新而不断更换新的版本。所以文档的内容可能前后不一致。 相信大家有能力克服这个问题。
本文档的字符图示在linux环境下显示正常,在window下显示有细微的错乱。
本文档唯一的更新网址是:http://wiki.zh-kernel.org/sniper 转载请保留此网址。
有任何建议请发邮件:s3c24xx@gmail.com
有任何问题请到邮件列表提问:http://zh-kernel.org/mailman/listinfo/linux-kernel
一些和内核调试分析有关的小工具放在:
http://code.google.com/p/root-kit/
一些前言
作者前言
一个人默默地敲打这篇文章也有段时间了。在这个过程里,没有收到任何的赞誉,也没接到任何的板砖,没有任何的反馈。就这么敲打着,修理着。但是本人从没怀疑这篇文档的价值,这是因为,本人就是这篇文档的亲身收益者。在这里把它“无私”奉献出来,乃是出于对于某类同道者锲而不舍孜孜以求的“德性”的认 同和“同情”,你的痛苦我表示感同身受,你的迷茫我愿意一起分担。一定有人能从个文档受益,这便已让我知足。其实,写这个文档并非是件苦差,而是字字都是有感而发的,不吐不快的结果。这里的句句都是本人教训和经验的记录。
谈到调试器,世上存在两种截然不同的看法。其中一种,是超级解霸的作者,他认为“程序不是写出来的,好程序绝对是调试出来的”。对于这个观点,本人持着极不认同的态度。而第二种相反观点的人,便是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 installlinux-doc-2.6.24
阅读Documentation/DocBook/ 下已经编译好的书籍(html格式)
$ firefox/usr/share/doc/linux-doc-2.6.24/html/index.html
10. 买书
11. 书籍最后面的参考书目
12. 文章末尾的参考文章
13. 电子书搜索网站
emule: 只要知道书名,windows下用emule基本可以找到所有的英文版电子书。
但在linux不行,可能是我的设置问题。
http://rapidshare.com/index.html
http://www.netbks.com/
为什么撰写本文档
todo:学习方法,学习曲线,参考书籍的特点和不足,本文档的任务
内核学习曲线
1.只读书不看源码
参考书籍:Linux KernelDevelopment
2.参考源码读书(读书为主)
参考书籍:understandingthe 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));
((structbuffer_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(conststruct 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) “发布—订阅”模型
例子:notificationchain
建立调试环境
发行版的选择和安装
为什么选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
如不特别说明,本文档所有命令都是在ubuntuHardy Heron8.04版本 和debian testing版本下的操作。
从0安装debian
[如果想领教古典linux相对于windows的特色,请安装一次debian吧。尽管和以前比,已经很智能了。但安装了debian,选了中文环境, 发现汉字都是歪歪倒倒的。而且没有汉字输入法,装了汉字输入法后,却用不了。不知道是我笨还是程序有bug.所以不得不用英文写下本烂文,怕把安装过程给 忘了。需要翻译回中文]
How to install andconfigure a debian system from zero
1.install the systemwith one CD
Download CD iso filefrom debian official website, and burn it into a CD. Note that, we can justdownload the first CD iso but not DVDs or the whole serials of CDs, because thefirst CD has already contained all the basis components of dedian system andmany other most common applications. We can use the first CD to install debiansystem, and then to install some other needed programs from it if needed. Inthis way, you can save much time spent on touching many inrelatived things.
2.installapplication & tool from CD
ou can install somecommon apllications from the CD with the following commnad: apt-get installexpected-application. Why can we do that without any more configuration? Why isit not need to has a ability to access internet? Well, Let’slook at the file named sourse.list which idenifying where to get software’s pakage?? deb cdrom:[Debian GNU/Linux testing _Lenny_ - OfficialSnapshot i386 CD Binary-1 20080605-15:01]/ lenny main It means that system tryto get somethig from your CD, so obviously that you can get some the mostcommon but not all the tools available in debian official apllicationrepository.
3.try to access theinternet
Thank to the firstCD, 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 usefulinformation through the internet
now, we have built abase debian system, but it is too simple. I want to do some some thing, forexample, to chat with some other people with pidgin, but it is not contained inthe first CD, which just downloaded by you. And you may want to search somehelps with google,etc. Just to do it, google is a most useful tool.
5.search theinternet updating source
I think you have getmuch thing through the google. But the most important thing is to get a availableupdate source for your system, and change the source.list–thatis /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 filesource.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/ lennymain contrib non-free
deb http://security.debian.org/lenny/updates main
deb-src http://security.debian.org/lenny/updates main
You should note thatthe internet address is debian office’s, but It takessome while to get it. And my searching tool is google. :) Oh, we shoul run acommand to update the new configuration to system before using it, don’t ferget: apt-get update
6.get helpfrom IRC
Well, we havealready been able to get some applications or tools from internet with commandapte-get or wget,etc.. But I think the first thing to do is to get and installa very valuable tool named pidgin which can bring you into IRC world.Because Many experiance and kind person live in channel #debian ofirc.freenode.net. You can get help from it very quickly. How to configurepidgin? Sorry, I don’t like to answer such a problem , please just to googleit or try it by yourselft. I am not so kind as some guys livingin IRC : )
7.get and installsynaptic
If you ever usedubuntu, you should agree that synaptic is good tool to update you system. Itcan save you much time of searching tools, typing commnad, or managing thedownloaded tools. But Unfortunately, such a important tool is not installed inthe default system, and it is not contained in the first CD. So, We can just toget it with command “apt-get install synaptic”. Afterdoing that successfully, I don’t want to type thatcommand anymore. It’s so tedious to me.
8.get more toolswith the help of synaptic
synaptic is my GODin 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 toupdate your system. And now, the CD used to install debian can be discarded, ifyou will never reinstall or rescure the system with it in future.
Now, the sun hasraise up, and you have found the road to reback to civilization. Why? Just toask 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 InputMethod" "gtk20" "/usr/share/locale" "ko:ja:th:zh"
改成:
"xim" "X InputMethod" "gtk20" "/usr/share/locale""en:ko:ja:th:zh"
注意,一定要重启一下机器。
pdf乱码的解决
$sudo apt-get installxpdf-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-essentialautoconf automake1.9 cvs subversion libncurses5-dev git rar unrar p7zip-fullcabextract
其余的根据出错的提示,利用“立新得”搜索,然后进行安装。没有“立新得”界面程序的可以在终端下利用以下命令来搜索和安装。
$ sudo apt-get update
$ apt-cache search XXX
$ sudo apt-get install XXX
双硬盘系统切换设置的grub设置,私人备忘用
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 forARM
Target OS Download
EABI Sourcery G++ Lite 2008q1-126
All versions...
uClinux SourceryG++ 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 inthese 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-200417:36 -
[ ] crosstool-0.27-gcc3.4.1.tar.gz 28-Jul-2004 17:21 2.0M
[ ] gcc-build-cross-3.3 31-Oct-200315: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 asroot 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. Thesource 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-srchttp://buildd.emdebian.org/debian/ unstable main
deb http://buildd.emdebian.org/debian/testing main
deb-srchttp://buildd.emdebian.org/debian/ testing main
然后:
安装 emdebian-archive-keyring package
$ sudo apt-get installemdebian-archive-keyring
更新
$ sudo apt-get update
2. 安装交叉编译器
$ sudo apt-get install libc6-armel-crosslibc6-dev-armel-cross binutils-arm-linux-gnueabi gcc-4.3-arm-linux-gnueabig++-4.3-arm-linux-gnueabi
注意,在ubuntu8.04下,只能安装4.2版。把上面文字中的4.3全部换为4.2即可。
3. 安装交叉调试器
$sudo apt-get installgdb-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 removegdb-arm-linux-gnueabi
sudo apt-get install apport apport-gtkapport-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 aspecific execution environment. For example, the Linux ABI for the ARMArchitecture.
2).A particular aspect of the specifications to which independently producedrelocatable files must conform in order to be statically linkable andexecutable. For example, the C++ ABI for the ARM Architecture, the Run-time ABIfor 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: 关于kernelARM_EABI http://zh-kernel.org/pipermail/linux-kernel/2008-January/002793.html
Why ARM’sEABI matters http://www.linuxdevices.com/articles/AT5920399313.html
Why switch toEABI? 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 | tarxvf -
4.如何卸载已安装的arm-elf-tools? 答,重新安装一次,注意看终端提示。或直接viarm-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处理器相关的编译选项
$ viarch/arm/Makefile
阅读Makefile文件,并联系源码根目录下的.config文件,便能知道arm-linux-gnueabi-gcc用了哪些编译选项。再到手册中查找,便能知道这些选项是干什么用的,但手册中说的不是很详细。另外查找有用解释的方法的是,利用make ARCH=armCROSS_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 :=$(callcc-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 isonly useful if you are using a user │
│ space environment that is also compiled with EABI. │
│ │
│ Since there are major incompatibilities between the legacy ABIand │
│ 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 compatibilitysupport │
│ (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 atarch/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 aremovable 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了 sendkeyctrl-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/
“Introducinginitramfs, 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/ -oinitrd.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 thekgdb 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 LinuxKernel 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=32256debian.img /mnt
拷贝完后,在真机上卸载虚拟硬盘
$ sudo umount /mnt
5.启动虚拟机,进入旧系统,在新内核源码根目录下用以下命令给qemu的虚拟系统安装一个新的内核
拷贝模块
$ make modules_install
安装内核
$ make install
制作initrd.img
$ cd /boot
$ mkinitramfs /lib/modules/2.6.26/ -oinitrd.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 SoftwareFoundation, Inc.
License GPLv3+: GNU GPL version 3 orlater <http://gnu.org/licenses/gpl.html>
This is free software: you are free tochange and redistribute it.
There is NO WARRANTY, to the extentpermitted by law. Type "showcopying"
and "show warranty" fordetails.
This GDB was configured as"i486-linux-gnu"...
0x0000fff0 in ?? ()
Breakpoint 1 at 0xc037f5ca: fileinit/main.c, line 535.
(gdb) c
Continuing.
Breakpoint 1, start_kernel () atinit/main.c:535
535 {
(gdb)
调试示意图:
给sys_read下断点
(gdb) b sys_read
Breakpoint 2 at 0xc017585e: filefs/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 intfput_needed; │
│358 │
│359 file =fget_light(fd, &fput_needed); │
B+>│360 if (file) { │
│361 loff_tpos = 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 <sys_read> push %ebp │
│0xc017585b <sys_read+1> mov %esp,%ebp │
│0xc017585d <sys_read+3> push %esi │
B+>│0xc017585e<sys_read+4> mov $0xfffffff7,%esi │
│0xc0175863 <sys_read+9> push %ebx │
│0xc0175864 <sys_read+10> sub $0xc,%esp │
│0xc0175867 <sys_read+13> mov 0x8(%ebp),%eax │
│0xc017586a <sys_read+16> lea -0xc(%ebp),%edx │
│0xc017586d <sys_read+19> call 0xc0175f65<fget_light> │
│0xc0175872 <sys_read+24> test %eax,%eax │
│0xc0175874 <sys_read+26> mov %eax,%ebx │
│0xc0175876 <sys_read+28> je 0xc01758b1<sys_read+87> │
│0xc0175878 <sys_read+30> mov 0x24(%ebx),%edx │
│0xc017587b <sys_read+33> 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 anemulated ARM machine http://www.aurel32.net/info/debian_arm_qemu.php
下面是过程的提炼步骤,方便查看。
1.创建虚拟硬盘
$ qemu-img create -fqcow hda.img 40G
2.下载必要文件
$ wgethttp://people.debian.org/~aurel32/arm-versatile/vmlinuz-2.6.18-6-versatile
$ wgethttp://people.debian.org/~aurel32/arm-versatile/initrd.img-2.6.18-6-versatile
$ wgethttp://ftp.de.debian.org/debian/dists/etch/main/installer-arm/current/images/rpc/netboot/initrd.gz
2.安装系统
qemu-system-arm -M versatilepb -kernelvmlinuz-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 -kernelvmlinuz-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 -ilinux-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 onQemu
http://909ers.apl.washington.edu/~dushaw/ARM/#SYSTEM
Running Linux forARM processors under QEMU
http://iomem.com/index.php?archives/2-Running-Linux-for-ARM-processors-under-QEMU.html&serendipity[entrypage]=2
Debian on anemulated 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 UserManual http://www.skyeye.org/wiki/UserManual
http://skyeye.wiki.sourceforge.net/
参考文档:
Linux-2.6.20 on XXXplatform
http://skyeye.wiki.sourceforge.net/Linux
uClinux-dist-20070130on 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.imgskyeye.conf vmlinux
3.运行虚拟机
$skyeye -e vmlinux
注意下面的提示,说明平时要注意在启动命令前加上sudo
NOTICE: you should be root at first !!!
NOTICE: you should inmod linux kernelnet 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 cannot support!!!
NOTICE: Please read SkyEye.README andtry 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=ttyS0initrd=0xc0800000,0x00800000 rw mem=64M
4. 把下载到的skyeye_2.6.17_lubbock.config更名为.config
5. 编译内核
make ARCH=armCROSS_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=armCROSS_COMPILE=arm-linux-gnueabi- s3c2410_defconfig
3.修改配置文件
make ARCH=armCROSS_COMPILE=arm-linux-gnueabi- menuconfig
进入[Device Driver] ->[ Character Driver] -> [SerialDriver] 等菜单下 ,
取消8250/16550 and compatible serial support的选择
4.修改内核启动命令
在Boot option --> Default kernel command string 里输入
mem=32M console=ttySAC0 root=/dev/raminitrd=0xc0800000,0x00800000 ramdisk_size=2048 rw
5.编译
make ARCH=armCROSS_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$ sudoskyeye -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-incommands.
/bin/ash: can't access tty; job controlturned off
/ $ uname -a
Linux skyeye 2.6.26 #2 Sun Oct 519: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 addr0x805f030
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 execfile.
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 SoftwareFoundation, Inc.
License GPLv3+: GNU GPL version 3 orlater <http://gnu.org/licenses/gpl.html>
This is free software: you are free tochange and redistribute it.
There is NO WARRANTY, to the extentpermitted by law. Type "showcopying"
and "show warranty" fordetails.
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 <stext> msr CPSR_c, #211 ; 0xd3 │
│0xc0008004 <stext+4> mrc 15, 0, r9, cr0, cr0,{0} │
│0xc0008008 <stext+8> bl 0xc00082f8<__lookup_processor_type> │
│0xc000800c <stext+12> movs r10, r5 │
│0xc0008010 <stext+16> beq 0xc0008190<__error_p> │
│0xc0008014 <stext+20> bl 0xc0008358<__lookup_machine_type> │
│0xc0008018 <stext+24> movs r8, r5 │
│0xc000801c <stext+28> beq 0xc00081e8<__error_a> │
│0xc0008020 <stext+32> bl 0xc00083a0<__vet_atags> │
│0xc0008024 <stext+36> bl 0xc0008078<__create_page_tables> │
│0xc0008028 <stext+40> ldr sp, [pc, #240] ; 0xc0008120 <__switch_data> │
└────────────────────────────────────────────────────────────────────────────────────────────────────┘
remote Thread 42000 In: stext Line: 80 PC: 0xc0008000
(gdb) b sys_read //下断点
Breakpoint 1 at 0xc008cc4c: filefs/read_write.c, line 354.
(gdb) c
----------------
调试示意图
效果可能与你机器上看到的不一样。这个例子中,每个gdb单步指令都会自动显示backtrace。这是因为本人使用了章节“gdb宏”中的extendinstr宏。
┌──include/asm/thread_info.h──────────────────────────────────────────────────────────────────────────────────────────────┐
│91 */ │
│92 static inline structthread_info *current_thread_info(void) __attribute_const__; │
│93 │
│94 static inline structthread_info *current_thread_info(void) │
│95 { │
│96 register unsignedlong sp asm ("sp"); │
>│97 return(struct thread_info *)(sp & ~(THREAD_SIZE - 1)); │
│98 } │
│99 │
│100 /* thread informationallocation */ │
│101 #ifdefCONFIG_DEBUG_STACK_USAGE │
│102 #definealloc_thread_info(tsk) │
│103 ((structthread_info *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, │
│104 THREAD_SIZE_ORDER)) │
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
│0xc008d480 <fget_light> mov r12, sp │
│0xc008d484 <fget_light+4> push {r11, r12, lr, pc} │
│0xc008d488 <fget_light+8> sub r11, r12, #4 ; 0x4 │
│0xc008d48c <fget_light+12> bic r3, sp, #8128 ; 0x1fc0 │
>│0xc008d490 <fget_light+16> bic r3, r3, #63 ; 0x3f │
│0xc008d494 <fget_light+20> ldr r3, [r3, #12] │
│0xc008d498 <fget_light+24> mov r12, #0 ; 0x0 │
│0xc008d49c <fget_light+28> ldr r2, [r3, #560] │
│0xc008d4a0 <fget_light+32> str r12, [r1] │
│0xc008d4a4 <fget_light+36> ldr r3, [r2] │
│0xc008d4a8 <fget_light+40> cmp r3, #1 ; 0x1 │
│0xc008d4ac <fget_light+44> bne 0xc008d4d0<fget_light+80> │
│0xc008d4b0 <fget_light+48> ldr r2, [r2, #4] │
│0xc008d4b4 <fget_light+52> ldr r3, [r2] │
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
remote Thread 42000 In: fget_light Line: 97 PC: 0xc008d490
Program received signal SIGHUP, Hangup.
0xc008d490 in fget_light (fd=1, fput_needed=0xc1c17ed4)at include/asm/thread_info.h:97
-------------------
#0 0xc008d490 in fget_light (fd=1, fput_needed=0xc1c17ed4) atinclude/asm/thread_info.h:97
#1 0xc008cc5c in sys_read (fd=1, buf=0xc1196800 "", count=512) atfs/read_write.c:359
#2 0xc000ac7c in rd_load_image (from=0xc02b43bc "/initrd.image")at init/do_mounts_rd.c:108
#3 0xc000bbe8 in initrd_load () at init/do_mounts_initrd.c:121
#4 0xc00094c0 in prepare_namespace () at init/do_mounts.c:384
#5 0xc0008a9c in kernel_init (unused=<value optimized out>) atinit/main.c:878
#6 0xc0048484 in sys_waitid (which=<value optimized out>,upid=-1044283692, infop=0x0, options=0, ru=Cannot access memory at
address 0x4
) at kernel/exit.c:1689
Backtrace stopped: previous frame innerto this frame (corrupt stack?)
(gdb)
使用最新的skyeye
1. 新版本的改进
在ubuntu下利用在线安装命令所安装的skyeye是旧的版本,新版本修正了旧版本的一些小问题。比如,旧版本在调试时会出现下面一些烦人的小提示。
Can't send signals to this remotesystem. SIGHUP not sent.
Program received signal SIGHUP, Hangup.
但是,两个版本并不是完全兼容的,主要是skyeye.conf的处理上。不过,幸好这些都是很容易解决的问题。
2. 新版本的安装
http://sourceforge.net/project/showfiles.php?group_id=85554
到上面的网站下载最新版本,目前是skyeye-1.2.6_rc1。解压后用下面命令编译就可以了
$./configure
$ make STATIC=1
然后把在源码根目录下生成的skyeye拷到内核目录下运行即可。这样系统中的老版本skyeye还照样可以使用。
sudo ./skyeye -d -e vmlinux
3. 新老版本的兼容问题
主要是skyeye.conf的格式识别上。老版本要求load_address,load_address_mask不能写在skyeye.conf文件内部,只能用-l选项指定。如果运行老版本时提示skyeye.conf出错,你就得去查查那里,并手动修改处理一下即可。
arm开发板调试环境的建立
基于串口
为qq2440平台移植2.6.26或更新内核,并建立kgdb调试环境
进行中...
[移植中的一些零碎的笔记]
1.内核版本
使用linus的git,但是已知2.6.25中arm已经支持kgdb了。
XXX@ubuntu:/storage/linus-git/linux-2.6$git-describe
v2.6.27-rc9-2-g85ba94b
2.
arm体系的默认配置文件在
arch/arm/configs
make ARCH=armCROSS_COMPILE=arm-linux-gnueabi- s3c2410_defconfig
make ARCH=armCROSS_COMPILE=arm-linux-gnueabi- menuconfig
选取以下选现
CONFIG_DEBUG_INFO=y
CONFIG_KGDB=y
CONFIG_KGDB_SERIAL_CONSOLE=y
make ARCH=armCROSS_COMPILE=arm-linux-gnueabi-
移植环境
windows:硬盘安装的真实系统(XP)
ubuntu: 运行在windows下的vmware虚拟机中
qq2440开发板:真实开发板,IP是192.168.1.230
第一天:(完成)
熟悉开发板,PC机,虚拟机的网络互连
理解内核启动过程
开发板与PC机(XP)PING不通的原因有
1. PC机开着防火
2. PC机上的VMWARE的网络设置有问题(先卸载确认)
3. 安全类软件造成,比如卡巴司机(先卸载,不行重装系统)
ubuntu的网络配置分两种情况,一种是平时上网用的,一种是和开发板通讯用的。
平时使用虚拟机ubuntu上网的配置:
连接方式选出NAT: used to share the host's IP address
虚拟系统启动后,桌面右上角的
wiredconnection->properties->configuration选automatic configuration(DHCP)
开发板挂载ubuntu虚拟系统中的nfs
1.虚拟机本身的网络设置不用动
2.虚拟系统如ubuntu的网卡设置改为桥接
edit virtual machinesettings->virtual machine setting->hardware->ethernet
->bridged:connected directly to thephysical network
3.虚拟系统启动后,桌面右上角的manual network configuration要改.
点左键->network settings->wiredconnection->properties:enable roaming mode不选,
connection settings
configuration:static IP address
IP address:192.168.1.111 与PC机IP,开发板IP同个网段
subnet mask:255.255.255.0
gateway address:空
PC机网络信息:
Ethernet adapter 本地连接:
Connection-specific DNS Suffix .:
IP Address. . . . . . . . . . . . : 192.168.1.100
Subnet Mask . . . . . . . . . . . : 255.255.255.0
Default Gateway . . . . . . . . . :
开发板的网络信息:
[root@(none) /]# ifconfig
eth0 Link encap:Ethernet HWaddr08:00:3E:26:0A:5B
inet addr:192.168.1.230 Bcast:192.168.1.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:1011 errors:0 dropped:0 overruns:0 frame:0
TX packets:610 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:111858 (109.2 KiB) TXbytes:57276 (55.9 KiB)
Interrupt:53 Base address:0x300
windows打开ubuntu中的samba共享目录的方法
\192.168.1.111
ubuntu中nfs服务的安装和启用
$ sudo apt-get install nfs-common
$ sudo apt-get install nfs-kernel-server
$ sudo vi /etc/exports
/new/root_nfs *(rw,sync)
$ sudo /etc/init.d/nfs-kernel-serverstart
4. 檢查
$ showmount -e localhost
开发板挂载nfs成功后可看到显示结果是
All mount points on localhost:
192.168.1.230:/new/root_nfs
开发板挂载ubuntu中的nfs
(此时运行的文件系统还是在开发板上)
mount -t nfs -o nolock192.168.1.111:/new/root_nfs /tmp/fuck
192.168.1.111:ubuntu的IP
/tmp/fuck:开发板中的挂载点
[root@(none) /]# mount -t nfs -o nolock192.168.1.111:/new/root_nfs /tmp/fuck
[root@(none) /]# cd /tmp/fuck/
[root@(none) fuck]# ls
bin lib proc usr
dev linuxrc sbin var
etc mnt shanghaitan.mp3 www
home opt tmp
-----
通过nfs启动开发板
(挂载的文件系统是在ubuntu虚拟系统上)
下面文字来自于:Embedded Linux Primer: A Practical,Real-World Approach
ip=192.168.1.139:192.168.1.1:192.168.1.1:255.255.255.0:coyote1:eth0:off
ip=<client-ip>:<server-ip>:<gw-ip>:<netmask>:<hostname>:<device>:<PROTO>
Here, client-ip is the target's IPaddress; server-ip is the address of the NFS server; gw-ip is the gateway(router), in case the server-ip is on a different subnet; and netmask definesthe class of IP addressing. hostname is a string that is passed as the targethostname; device is the Linux device name, such as eth0; and PROTO defines theprotocol used to obtain initial IP parameters.
本人的实际操作的命令参数是:
param set linux_cmd_line"console=ttySAC0 root=/dev/nfs nfsroot=192.168.1.111:/new/root_nfsip=192.168.1.130:192.168.1.111:192.168.1.111:255.255.255.0:sbc2440.arm9.net:eth0:off"
注意把编辑器的换行功能去掉后,再复制上面的命令。
192.168.1.130是开发板的IP,系统启动后,用ifconfig就会显示这个IP地址。可以随意设置,当然要满足和PC机,ubuntu的IP在同个网段,而且不能冲突的先前条件。
130:192.168.1.111:nfs的server,也就是ubuntu的IP
按住空格健重启开发板,出现:
+---------------------------------------------+
| S3C2440A USB Downloader ver R0.03 2004Jan |
+---------------------------------------------+
USB: IN_ENDPOINT:1 OUT_ENDPOINT:3
FORMAT:<ADDR(DATA):4>+<SIZE(n+10):4>+<DATA:n>+<CS:2>
NOTE: Power off/on or press the resetbutton for 1 sec
in order to get a valid USB device address.
NAND device: Manufacture ID: 0xec, ChipID: 0x76 (Samsung K9D1208V0M)
Found saved vivi parameters.
Press Return to start the LINUX/Wincenow, any other key for vivi
type "help" for help.
Supervivi> menu
##### FriendlyARM BIOS for 2440 #####
[x] bon part 0 320k 2368k
[v] Download vivi
[k] Download linux kernel
[y] Download root_yaffs image
[c] Download root_cramfs image
[n] Download Nboot
[e] Download Eboot
[i] Download WinCE NK.nb0
[w] Download WinCE NK.bin
[d] Download & Run
[f] Format the nand flash
[p] Partition for Linux
[b] Boot the system
[s] Set the boot parameters
[t] Print the TOC struct of wince
[q] Goto shell of vivi
Enter your selection: s //<--
##### Parameter Menu #####
[r] Reset parameter table to defaulttable
[s] Set parameter
[v] View the parameter table
[w] Write the parameter table to flashmemeory
[q] Quit
Enter your selection: s //<--
Enter the parameter's name(mach_type,media_type, linux_cmd_line, etc): linux_cmd_line
Enter the parameter's value(if the valuecontains space, enclose it with "): "console=ttySAC0 root=/dev/nfsnfsroot=192.168.1.111:/new/root_nfsip=192.168.1.130:192.168.1.111:192.168.1.111:255.255.255.0:sbc2440.arm9.net:eth0:off"
Change linux command line to"console=ttySAC0 root=/dev/nfs nfsroot=192.168.1.111:/new/root_nfsip=192.168.1.130:192.168.1.111:192.168.1.111:255.255.255.0:sbc2440.arm9.net:eth0:off"
##### Parameter Menu #####
[r] Reset parameter table to defaulttable
[s] Set parameter
[v] View the parameter table
[w] Write the parameter table to flashmemeory
[q] Quit
Enter your selection: w //<--
Found block size = 0x0000c000
Erasing... ... done
Writing... ... done
Written 49152 bytes
Saved vivi private data
第二天:(完成)
文件系统制作
理解系统启动过程
先实验在skyeye下能不能成功,学习一下文件系统的制作。而后再下载到开发板实验
dd if=/dev/zero of=./test.image bs=1kcount=8192
块大小单位:1k,8120块,8M
mke2fs ./test.image
格式化
mkdir fuckroot
tar -xzvf root_mini.tgz
sudo mount -o loop test.image./fuckroot/
cp -r root_mini/* fuckroot/
sudo umount fuckroot/
可以将文件系统映像压缩后再使用:
gzip -v9 test.image > test.image.gz
本人这个文件系统解压后的大小是6.4M,制作成8M大的test.image,压缩成test.image.gz后只有2.9M大。
但是利用skyeye启动时,解压花的时间比较长。
命令行中的ramdisk_size太小,修改.
mem=32M console=ttySAC0 root=/dev/raminitrd=0xc0800000,0x00800000 ramdisk_size=8192 rw initcall_debug
ramdisk_size=N
This parameter tells the RAM disk driverto set up RAM disks of N k size.
问题,文件系统没创建console设备节点:
RAMDISK: Loading 8192KiB [1 disk] intoram disk... done.
VFS: Mounted root (ext2 filesystem).
Freeing init memory: 132K
Warning: unable to open an initialconsole.
创建rootfs过程中,在/dev目录下手动创建如下节点:
mknod -m 660 null c 1 3
mknod -m 660 console c 5 1
结果:
VFS: Mounted root (ext2 filesystem).
Freeing init memory: 132K
hwclock: Could not access RTC: No suchfile or directory
mknod: /dev/pts/0: No such file ordirectory
mount: Mounting none on /tmp failed:Invalid argument
mount: Mounting none on /var failed:Invalid argument
/etc/init.d/rcS: /etc/init.d/rcS: 44:cannot create /dev/vc/0: Directory nonexistent
/etc/init.d/rcS: /etc/init.d/rcS: 45:cannot create /dev/vc/0: Directory nonexistent
/etc/rc.d/init.d/httpd: /etc/rc.d/init.d/httpd:16: /sbin/boa: not found
/etc/init.d/rcS: /etc/init.d/rcS: 48:cannot create /dev/vc/0: Directory nonexistent
/etc/init.d/rcS: /etc/init.d/rcS: 49:cannot create /dev/vc/0: Directory nonexistent
/etc/rc.d/init.d/leds:/etc/rc.d/init.d/leds: 16: /etc/init.d/rcS: /etc/init.d/rcS: 52: cannot create/dev/vc/0: Directory nonexistent
/etc/init.d/rcS: /etc/init.d/rcS: 53:cannot create /dev/vc/0: Directory nonexistent
/sbin/led-player: not found
SIOCSIFADDR: No such device
SIOCGIFFLAGS: No such device
/etc/init.d/rcS: /etc/init.d/rcS: 59:/sbin/madplay: not found
Please press Enter to activate thisconsole.
-sh: can't access tty; job controlturned off
id: unknown uid 0
[@FriendlyARM /]# ls
bin home lost+found sbin var
dev lib mnt tmp www
etc linuxrc proc usr
[@FriendlyARM /dev]# ls
console dsp fb0 mixer null sda1 tty1 video0
还有一堆提示,但总算系统能跑了。
现在我的心头大患是udev的问题,因为2.6.26内核中没有devfs了。但有下面这篇文章参考
udev轻松上路
http://www.linuxforum.net/forum/showflat.php?Cat=&Board=embedded&Number=628054&page=0&view=collapsed&sb=5&o=0&fpart=
第三天:(完成)
移植内核2.6.27-rc9到qq2440开发板,实现基本功能,能挂载板上文件系统.
步骤:
1.使用vivi修改mach_type参数
2.修改时钟频率
3.修改源码正确分区
4.禁止nand的ECC校验
分述:
问题1.表现
UncompressingLinux.................................................................................................................done, booting the kernel.
Error: unrecognized/unsupported machineID (r1 = 0x0000030e).
Available machine support:
ID (hex) NAME
000000c1 SMDK2410
0000015b IPAQ-H1940
0000039f Acer-N35
00000290 Acer-N30
0000014b Simtec-BAST
000002a8 Nex Vision - Otom 1.1
00000400 AML_M5900
000001db Thorcom-VR1000
00000454 QT2410
000003fe SMDK2413
000003f1 SMDK2412
00000377 S3C2413
00000474 VSTMS
000002de Simtec-Anubis
0000034a Simtec-OSIRIS
00000250 IPAQ-RX3715
0000016a SMDK2440
000002a9 NexVision - Nexcoder 2440
0000043c SMDK2443
Please check your kernel config and/orbootloader.
解决方法:
##### Parameter Menu #####
[r] Reset parameter table to defaulttable
[s] Set parameter
[v] View the parameter table
[w] Write the parameter table to flashmemeory
[q] Quit
Enter your selection: s
Enter the parameter's name(mach_type,media_type, linux_cmd_line, etc): mach_type
Enter the parameter's value(if the valuecontains space, enclose it with "): 362 //<---
Change 'mach_type' value.0x0000030e(782) to 0x0000016a(362)
问题2.表现
UncompressingLinux.................................................................................................................done, booting the kernel.
8?'·{e#???;?·7'0??3G?#?G'?乱码
解决方法:
static void __init smdk2440_map_io(void)
{
s3c24xx_init_io(smdk2440_iodesc,ARRAY_SIZE(smdk2440_iodesc));
s3c24xx_init_clocks(12000000);//修改处,原为16934400
s3c24xx_init_uarts(smdk2440_uartcfgs,ARRAY_SIZE(smdk2440_uartcfgs));
}
问题3.表现
VFS: Cannot open root device"mtdblock2" or unknown-block(31,2)
Please append a correct"root=" boot option; here are the available partitions:
1f00 16 mtdblock0 (driver?)
1f01 2048 mtdblock1 (driver?)
1f02 4096 mtdblock2 (driver?)
1f03 2048 mtdblock3 (driver?)
1f04 4096 mtdblock4 (driver?)
1f05 10240 mtdblock5 (driver?)
1f06 24576 mtdblock6 (driver?)
1f07 16384 mtdblock7 (driver?)
Kernel panic - not syncing: VFS: Unableto mount root fs on unknown-block(31,2)
解决:
依据nand分区修改源码:
static struct mtd_partitionsmdk_default_nand_part[] = {
[0]= {
.name = "vivi",
.size = 0x00030000,
.offset = 0,
},
[1]= {
.name = "kernel",
.offset= 0x00050000,
.size = 0x00200000,
},
[2]= {
.name = "root",
.offset= 0x00250000,
.size = 0x03dac000,
},
};
问题4.表现
Kernel panic - not syncing: VFS: Unableto mount root fs on unknown-block(31,2)
导致上面panic的原因是没有禁止Flash ECC校验
解决:
s3c2410_nand_init_chip()
..
if(set->disable_ecc)
chip->ecc.mode = NAND_ECC_NONE;
chip->ecc.mode = NAND_ECC_NONE;//<-在函数最后加上
启动信息:
Copy linux kernel from 0x00050000 to0x30008000, size = 0x00200000 ... done
zImage magic = 0x016f2818
Setup linux parameters at 0x30000100
linux command line is: "noinitrdroot=/dev/mtdblock2 init=/linuxrc console=ttySAC0"
MACH_TYPE = 362
NOW, Booting Linux......
UncompressingLinux.................................................................................................................done, booting the kernel.
Linux version 2.6.27-rc9(fqh@ubuntu-sniper) (gcc version 4.2.4 (Debian 4.2.4-3)) #8 Sat Oct 11 03:17:21CST 2008
CPU: ARM920T [41129200] revision 0(ARMv4T), cr=c0007177
Machine: SMDK2440
ATAG_INITRD is deprecated; please updateyour bootloader.
Memory policy: ECC disabled, Data cachewriteback
CPU S3C2440A (id 0x32440001)
S3C244X: core 405.000 MHz, memory101.250 MHz, peripheral 50.625 MHz
S3C24XX Clocks, (c) 2004 SimtecElectronics
CLOCK: Slow mode (1.500 MHz), fast, MPLLon, UPLL on
CPU0: D VIVT write-back cache
CPU0: I cache: 16384 bytes,associativity 64, 32 byte lines, 8 sets
CPU0: D cache: 16384 bytes,associativity 64, 32 byte lines, 8 sets
Built 1 zonelists in Zone order,mobility grouping on. Total pages: 16256
Kernel command line: noinitrd root=/dev/mtdblock2init=/linuxrc console=ttySAC0
irq: clearing pending ext status00000200
irq: clearing subpending status 00000002
PID hash table entries: 256 (order: 8,1024 bytes)
timer tcon=00000000, tcnt a4ca, tcfg00000200,00000000, usec 00001e57
Console: colour dummy device 80x30
console [ttySAC0] enabled
Dentry cache hash table entries: 8192(order: 3, 32768 bytes)
Inode-cache hash table entries: 4096(order: 2, 16384 bytes)
Memory: 64MB = 64MB total
Memory: 61140KB available (3224K code,335K data, 144K init)
Calibrating delay loop... 201.93BogoMIPS (lpj=504832)
Mount-cache hash table entries: 512
CPU: Testing write buffer coherency: ok
net_namespace: 440 bytes
NET: Registered protocol family 16
S3C2410 Power Management, (c) 2004Simtec Electronics
S3C2440: Initialising architecture
S3C2440: IRQ Support
S3C24XX DMA Driver, (c) 2003-2004,2006Simtec Electronics
DMA channel 0 at c4800000, irq 33
DMA channel 1 at c4800040, irq 34
DMA channel 2 at c4800080, irq 35
DMA channel 3 at c48000c0, irq 36
S3C244X: Clock Support, DVS off
SCSI subsystem initialized
usbcore: registered new interface driverusbfs
usbcore: registered new interface driverhub
usbcore: registered new device driverusb
NET: Registered protocol family 2
IP route cache hash table entries: 1024(order: 0, 4096 bytes)
TCP established hash table entries: 2048(order: 2, 16384 bytes)
TCP bind hash table entries: 2048(order: 1, 8192 bytes)
TCP: Hash tables configured (established2048 bind 2048)
TCP reno registered
NET: Registered protocol family 1
NetWinder Floating Point Emulator V0.97(extended precision)
JFFS2 version 2.2. (NAND) (SUMMARY) © 2001-2006 Red Hat, Inc.
msgmni has been set to 119
io scheduler noop registered
io scheduler anticipatory registered(default)
io scheduler deadline registered
io scheduler cfq registered
Console: switching to colour framebuffer device 30x40
fb0: s3c2410fb frame buffer device
lp: driver loaded but no devices found
ppdev: user-space parallel port driver
Serial: 8250/16550 driver4 ports, IRQsharing enabled
s3c2440-uart.0: s3c2410_serial0 at MMIO0x50000000 (irq = 70) is a S3C2440
s3c2440-uart.1: s3c2410_serial1 at MMIO0x50004000 (irq = 73) is a S3C2440
s3c2440-uart.2: s3c2410_serial2 at MMIO0x50008000 (irq = 76) is a S3C2440
brd: module loaded
loop: module loaded
dm9000 Ethernet Driver, V1.31
Uniform Multi-Platform E-IDE driver
Driver 'sd' needs updating - please usebus_type methods
S3C24XX NAND Driver, (c) 2004 SimtecElectronics
s3c2440-nand s3c2440-nand: Tacls=3, 29nsTwrph0=7 69ns, Twrph1=3 29ns
NAND device: Manufacturer ID: 0xec, ChipID: 0x76 (Samsung NAND 64MiB 3,3V 8-bit)
NAND_ECC_NONE selected by board driver.This is not recommended !!
Scanning device for bad blocks
Bad eraseblock 562 at 0x008c8000
Bad eraseblock 566 at 0x008d8000
Creating 3 MTD partitions on "NAND64MiB 3,3V 8-bit":
0x00000000-0x00030000 : "vivi"
0x00050000-0x00250000 :"kernel"
0x00250000-0x03ffc000 : "root"
usbmon: debugfs is not available
s3c2410-ohci s3c2410-ohci: S3C24XX OHCI
s3c2410-ohci s3c2410-ohci: new USB busregistered, assigned bus number 1
s3c2410-ohci s3c2410-ohci: irq 42, iomem 0x49000000
usb usb1: configuration #1 chosen from 1choice
hub 1-0:1.0: USB hub found
hub 1-0:1.0: 2 ports detected
usbcore: registered new interface driverlibusual
usbcore: registered new interface driverusbserial
usbserial: USB Serial support registeredfor generic
usbcore: registered new interface driverusbserial_generic
usbserial: USB Serial Driver core
usbserial: USB Serial support registeredfor FTDI USB Serial Device
usbcore: registered new interface driverftdi_sio
ftdi_sio: v1.4.3:USB FTDI SerialConverters Driver
usbserial: USB Serial support registeredfor pl2303
usbcore: registered new interface driverpl2303
pl2303: Prolific PL2303 USB to serialadaptor driver
mice: PS/2 mouse device common for allmice
S3C24XX RTC, (c) 2004,2006 SimtecElectronics
s3c2440-i2c s3c2440-i2c: slave address0x10
s3c2440-i2c s3c2440-i2c: bus frequencyset to 98 KHz
s3c2440-i2c s3c2440-i2c: i2c-0: S3C I2Cadapter
S3C2410 Watchdog Timer, (c) 2004 SimtecElectronics
s3c2410-wdt s3c2410-wdt: watchdoginactive, reset disabled, irq enabled
TCP cubic registered
NET: Registered protocol family 17
RPC: Registered udp transport module.
RPC: Registered tcp transport module.
drivers/rtc/hctosys.c: unable to openrtc device (rtc0)
VFS: Mounted root (cramfs filesystem)readonly.
Freeing init memory: 144K
hwclock: Could not access RTC: No suchfile or directory
mknod: /dev/pts/0: Read-only file system
ln: /dev/video0: Read-only file system
ln: /dev/fb0: Read-only file system
ln: /dev/tty1: Read-only file system
ln: /dev/dsp: Read-only file system
ln: /dev/mixer: Read-only file system
ln: /dev/sda1: Read-only file system
/etc/init.d/rcS: /etc/init.d/rcS: 44:cannot create /dev/vc/0: Read-only file system
/etc/init.d/rcS: /etc/init.d/rcS: 45:cannot create /dev/vc/0: Read-only file system
/etc/rc.d/init.d/httpd:/etc/rc.d/init.d/httpd: 16: /sbin/boa: not found
/etc/init.d/rcS: /etc/init.d/rcS: 48:cannot create /dev/vc/0: Read-only file system
/etc/init.d/rcS: /etc/init.d/rcS: 49:cannot create /dev/vc/0: Read-only file system
/etc/rc.d/init.d/leds:/etc/rc.d/init.d/leds: 16: /sbin/led-player: not found
/etc/init.d/rcS: /etc/init.d/rcS: 52:cannot create /dev/vc/0: Read-only file system
/etc/init.d/rcS: /etc/init.d/rcS: 53:cannot create /dev/vc/0: Read-only file system
SIOCSIFADDR: No such device
SIOCGIFFLAGS: No such device
/etc/init.d/rcS: /etc/init.d/rcS: 59:/sbin/madplay: not found
Please press Enter to activate thisconsole.
-sh: can't access tty; job controlturned off
id: unknown uid 0
[@FriendlyARM /]# uname -a
Linux FriendlyARM 2.6.27-rc9 #8 Sat Oct11 03:17:21 CST 2008 armv4tl unknown
[@FriendlyARM /]#
第四天:
实现XP下虚拟机中的ubuntu利用gdb通过串口调试开发板上的2.6.27-rc9内核
问题,开发板只有一个串口,给gdb占用了,怎么操作开发板?
第五天:
实现硬盘安装的ubuntu系统利用gdb通过串口调试开发板上的内核。
第六天:
移植cs8900a网卡驱动。
实现开发板从硬盘ubuntu的nfs启动。
实现硬盘安装的ubuntu系统利用gdb通过网口调试开发板上的内核。
参考:
ubuntu8.04+skyeye1.2.4搭建linux2.6.24+s3c2410的模拟arm-linux开发环境
http://www.google.cn/search?complete=1&hl=zh-CN&newwindow=1&client=firefox-a&rls=org.mozilla:zh-CN:official&hs=R4b&q=cs8900+s3c2440+%E9%A9%B1%E5%8A%A8&start=20&sa=N
http://blog.chinaunix.net/u2/72751/showart_1130655.html
http://www.akae.cn/bbs/redirect.php?tid=6929&goto=lastpost
基于网口
gdb基础
基本命令
推荐这篇,内容很全: gdb 使用手册 http://blog.chinaunix.net/u/11240/showart.php?id=340632
终极参考: Debugging withGDB http://sourceware.org/gdb/current/onlinedocs/gdb.html#SEC_Top
gdb之gui
网址:
cgdb:http://cgdb.sourceforge.net/
kgdb:http://www.kdbg.org/screenshot.php
ddd:http://www.gnu.org/software/ddd/
insight:http://sourceware.org/insight/
这些工具在ubuntu下都有编译好的.deb安装包,利用“立新得”就直接搜索然后在线安装。
这篇短文是我的浅陋之见,我接触这些gui的时间也不久。错误难免。虚拟机:qemu
内核内置kgdb
developer machine: 运行gdb
除了只用命令行gdb外,还可以用gdb的gui,有
1.cgdb 缺点:界面简陋,自动化程度低,只是把terminal分为两部分,上面部分显示源码,下面打命令。由于没有显示反汇编的窗体,不适合要求使用到 stepi命令的场合。优点:运行快,锻炼手指头. 最大的优点是,它有完美的代码着色功能。其他几款调试器中都没有。
2.ddd: 缺点:与kdbg相比,界面凌乱。优点:代码显示效果比kdbg好,c和反汇编代码分开在两个窗口。 可以随时暂停程序的运行。data windows 这个功能非常强大灵活。提示 ddd –tty 2>/dev/null ./vmlinux ; remotetarget localhost:1234
3. kdbg: 缺点:功能比ddd弱。字体太小,c和反汇编代码交错显示,反汇编代码折叠隐藏在C代码之间,要显示反汇编代码要手动展开,不可忍受。太过界面化,居然找 不到是在哪里手动打gdb命令。致命缺点是,内核跑起来后,如果没有断点拦截,就没法把内核的运行暂停下来,kdbg成了没事姥,源码窗口的显示不更新。 另一个致命缺点是,如果没有源码只有二进制文件,虽然可以下断点,但无法显示反汇编代码,没意义。据说kdbg是用来调试kde程序的,实际上也能调试内 核。优点:窗口可以整合到一块,稳定。有变化的寄存器会显示红色。提示 kdbg -r localhost:1234 ./vmlinux
4. insight: 和ddd都是基于TCL/TK,比较相似。优点:源码显示功能最强,可以选择C和反汇编代码分开和交叉显示。可以选择反汇编代码使用intel还是 at&t格式。可以列出当前有哪些源文件,当前文件有哪些函数。变化的寄存器有改变颜色的功能,ddd则没有。缺点:和ddd一样,小窗口无法整 合到到窗口中,但比ddd差的是,主窗口最大化后小窗口无法保持置顶。相对ddd的大劣势是没有一个强大的data windows。感觉界面比ddd强大,但灵活性比ddd差点。对于调试内核来说,还有一个和kdbg相同的大缺点,内核只能通过断点暂停运行,而ddd 下还可以用ctrl+c暂停内核。另外它有个SB错误,显示backtrace的窗口,标题居然是stack. 提示: insight ./vmlinux
5. xxgdb: 古董级别。没事干的时候可以玩玩
6. 其实,gdb自带了一个基于curses的gui。启动方式是gdbtuixxx; 或者在gdb启动之后用命令layout启动gui。很好用,可以至多同时显示三个分窗口。要是代码有着色功能就好了。
针对内核调试的总结:
1. kdbg不适合调试内核
3. 如果想复习gdb强大的命令,选cgdb或纯gdb。
4. 如果想学习汇编,insight是不二选择。
5 如果倾向于把调试器当作浏览器使用,作为source insight等工具的辅助工具,在内核运行中拦截函数,分析函数的调用关系,不需要反汇编的话,则cgdb是不错的选择 .(source insight等源码分析工具有个共同的缺点,因为体系和内核配置不同,一个函数有很多的定义,借助调试器可以在内核运行的时候找出实际调用的那个)
6.insight和ddd很接近,各有千秋。但如果侧重于追溯数据结构体间的联系,ddd更好一点,因为它有data window,它的强项是数据和数据结构关系分析并用图像方式显示出来(What is DDD? Data Display Debugger)。如果侧重于分析汇编指令是怎么在cpu中跑的,推荐用insight,因为它汇编代码显示功能更细致。
7.可惜目前在ubuntu8.04下,ddd+qemu组合用来调试驱动时有bug:驱动函数被拦截时如果正在qemu的系统下操作,鼠标就会冻结在qemu的屏幕中。其实调试单个驱动,用gdb就足够了。ddd等gui一般用来调试理解内核原理。
gdb技巧
另外有用的命令 ptype,whatis
----
更多相关技巧:
1. 获取structpage结构的大小
(gdb) p mem_map
$80 = (struct page *) 0xc1000000
(gdb) p mem_map+1
$81 = (struct page *) 0xc1000020
(gdb) p/x 0xc1000020 - 0xc1000000
$82 = 0×20
2.
打印前从指针mem_map所指起的5个page结构体
(gdb) p *mem_map@5
$83 = {{flags = 1024, _count = {counter= 1}, {_mapcount = {counter = -1}, {inuse = 65535, objects = 65535}}, {{private= 0, mapping = 0×0}, ptl =…
用ddd的图形显示命令是 (gdb) graph display *mem_map@5
参考 p *array@len
@的左边是数组的首地址的值,也就是变量array所指向的内容,右边则是数据的长度,其保存在变量len中
3.
每运行一次stepi/next等命令后显示下一步要将要运行的反汇编指令
(gdb) display/i $pc
6: x/i $pc
0xc0144fb6<init_cgroup_root+22>: mov %esp,%ebp
(gdb) stepi
6: x/i $pc
0xc0144fb8 <init_cgroup_root+24>: mov %edx,0×44(%eax)
提示:display的管理:
undisplay deletedisplay disable display enable display info display
4.使结构体的显示更漂亮
(gdb) show print pretty
Prettyprinting of structures is on.
(gdb) set print pretty off
(gdb) p *init_task->group_info
$12 = {ngroups = 0, usage = {counter =14}, small_block = {0 <repeats 32 times>}, nblocks = 0, blocks =0xc0355530}
(gdb) set print pretty on
(gdb) p *init_task->group_info
$13 = {
ngroups = 0,
usage = {
counter = 14
},
small_block = {0 <repeats 32times>},
nblocks = 0,
blocks = 0xc0355530
}
(注:6.7.条来自http://techcenter.dicder.com/2006/0906/content_173.html)
5. 使用自定义命令。
(gdb) define nid
Type commands for definition of “nid”.
End with a line saying just “end”.
>ni
>disassemble $pc $pc+16
>end
6. 纯gdb的多窗口显示 GUI调试器可以同时打开多个小窗口,分别显示寄存器、汇编和源代码等。在gdb里也可以做到,但同时最多只能显示两个窗口,试了一下也很方便的。基本命令如下:
a) `layout src’ 仅显示源代码窗口。
b) `layout asm’ 仅显示汇编代码窗口。
c) `layout split’ 显示源代码和汇编代码窗口。
d) `layout regs’ 显示寄存器和源代码窗口,或者寄存器和汇编代码窗口。
e) `layout next` 和`layout prev’ 切换窗口。
f) ctrl + L 刷新屏幕。
g) `C-x 1′ 单窗口模式。
h) `C-x 2′ 双窗口模式。
i) `C-x a’ 回到传统模式。
7. 字符gdb中,如何在每执行一次next命令后都自动显示backtrace的内容 这个问题实际是如何一次执行多条命令。用自定义命令解决
(gdb) define nbt
Type commands for definition of “nbt”.
End with a line saying just “end”.
>next
>bt
>end
(gdb) nbt
#0 early_cpu_init () at arch/x86/kernel/cpu/common.c:626
#1 0xc0384ca9 in setup_arch (cmdline_p=0xc0379fe8)
at arch/x86/kernel/setup_32.c:765
#2 0xc037f62e in start_kernel () at init/main.c:564
#3 0xc037f008 in i386_start_kernel () at arch/x86/kernel/head32.c:13
#4 0×00000000 in ?? ()
(gdb)
8. gdb在TUI模式下如何把光标焦点炸转移到command窗口,以便能用上下箭头键能快速翻出历史指令?
实际是转换“active”窗口。
C-x o: ctrl+x,接着放开这两个键,然后在按o(不需要+ctrl)
关于TUI更多信息:
http://sourceware.org/gdb/current/onlinedocs/gdb_23.html#SEC236
还有组合键
C-x C-a
C-x a
C-x A 退出TUI模式
C-x 1 只用一个窗口
C-x 2 用两个窗口,按多次会有不同两个窗口的组合形式
C-x o active 窗口转移
C-x s 进入和退出TUI SingleKey 模式
注:C-x o多次使用相当于依次执行以下命令
focus src 转移焦点到源码窗口。
focus asm
focus regs
focus cmd
TUI模式还有以下专用命令
info win
layout next
layout prev
layout src
layout asm
layout split
layout regs
focus next
refresh
tui reg float
tui reg general
tui reg next
tui reg system
update
winheight name +count
winheight name -count
tabset nchars
9. 如何在子函数调用和退出时都暂停运行 watch $ebp
10. 如何获取结构体中特定域的相对偏移量,比如struct stak_struct 中lock_depth的相对偏移量?
(gdb) p/x &(*(struct task_struct*)0).lock_depth
$7 = 0x14
11. 如何能够交换使用ddd与gdb,也就是说使用ddd调试时,想换回使用纯gdb,同时保证启用gdb后保证“调试上下文”没任何变化?
只要.gdbinit 文件没包含 c, next..等等能驱动gdb继续调试的命令就可以。
12. 如何通过函数名确定所在的源文件
(gdb) info line vfs_mkdir
Line 2131 of "fs/namei.c"starts at address 0xc017c048 <vfs_mkdir> and ends at 0xc017c052<vfs_mkdir+10>.
13. 由汇编指令地址确定该指令所对应源码的所在行(注:一行c语言一般对应几行汇编指令)
info line *xxxxxxx(xxx是汇编指令地址)
14. 如何快速定位函数中某句C语句对应汇编指令的开始地址。比如以下 [内容太大,准备移到其他位置]
2130 intvfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
2131 {
.......
2145 DQUOT_INIT(dir);
2146 error= dir->i_op->mkdir(dir, dentry, mode);//<-我们想确定这句语句的汇编指令开始地址,注意它在源文件中的行数
2147 if(!error)
2148 fsnotify_mkdir(dir,dentry);
2149 returnerror;
2150 }
首先,通过函数名查询对应的源文件
(gdb) info line vfs_mkdir
Line 2131 of "fs/namei.c"starts at address 0xc017c048 <vfs_mkdir> and ends at 0xc017c052<vfs_mkdir+10>.
然后,利用info line 源文件:目标语句的行数 就能查询到
(gdb) info line fs/namei.c:2146
Line 2146 of "fs/namei.c"starts at address 0xc017c0ee <vfs_mkdir+166> and ends at 0xc017c0fe<vfs_mkdir+182>.
验证一下
(gdb) disass 0xc017c0ee
Dump of assembler code for functionvfs_mkdir:
0xc017c048 <vfs_mkdir+0>: push %ebp
.....
0xc017c0e4 <vfs_mkdir+156>: mov 0x24(%eax),%ecx
0xc017c0e7 <vfs_mkdir+159>: or $0xffffffff,%edx
0xc017c0ea <vfs_mkdir+162>: mov %esi,%eax
0xc017c0ec <vfs_mkdir+164>: call *(%ecx)
0xc017c0ee <vfs_mkdir+166>: mov 0x98(%esi),%ebx //
0xc017c0f4 <vfs_mkdir+172>: mov %edi,%edx //参数 dentry -> %edx
0xc017c0f6 <vfs_mkdir+174>: mov %esi,%eax //参数dir -> %eax
0xc017c0f8 <vfs_mkdir+176>: mov -0x10(%ebp),%ecx //参数mode -> %ecx
0xc017c0fb <vfs_mkdir+179>: call *0x14(%ebx) //dir->i_op->mkdir(dir, dentry, mode)
0xc017c0fe <vfs_mkdir+182>: test %eax,%eax //判断返回值(error = dir->i_op->mkdir(dir,dentry, mode);)
0xc017c100 <vfs_mkdir+184>: mov %eax,%ebx //保存返回值
0xc017c102 <vfs_mkdir+186>: jne 0xc017c15d <vfs_mkdir+277> //如果返回值 != 0,也就是mkdir失败,跳到最后返回。成功则继续
0xc017c104 <vfs_mkdir+188>: testb $0x4,0x11c(%esi) //内联函数fsnotify_mkdir 及子函数->inode_dir_notify在这里展开
//static inline voidinode_dir_notify(struct inode *inode, unsigned long event)
//{
// if (inode->i_dnotify_mask &(event)) <-注意这里判断位,刚好对应testb $0x4,0x11c(%esi)
0xc017c10b <vfs_mkdir+195>: je 0xc017c119 <vfs_mkdir+209>
.....
0xc017c15d <vfs_mkdir+277>: lea -0xc(%ebp),%esp
0xc017c160 <vfs_mkdir+280>: mov %ebx,%eax
我们通过mkdir参数个数,及testb 指令基本判定我们的猜测没错。也就是说vfs_mkdir函数中dir→i_op→mkdir的实际调用是在0xc017c0fb <vfs_mkdir+179>: call *0×14(%ebx)
15. 下断点的形式
1. b 函数名
2. b *指令地址
3. b 源码:行数
(gdb) b fs/namei.c:2146
Breakpoint 9 at 0xc017c0ee: filefs/namei.c, line 2146.
16. 陷入循环语句后,想自动运行到循环语句结束:
u
17. 重复当前的gdb指令
按enter键即可
gdb宏
本小节意义:为了方便把调试内容复制出来,而又需要一定的功能,本人经常使用的工具是gdb的tui。所以gdb宏的使用更是成了不可缺少的辅助手段。比如extendinstr宏,能实时显示调用链的情况,相当于实现了ddd的backtrace分窗口。其他宏的作用就不说了。
参考资料
kgdb官方的gdb宏 http://kgdb.linsyssoft.com/downloads.htm
“Fun with strace andthe GDB Debugger” http://www.ibm.com/developerworks/aix/library/au-unix-strace.html
“GNU ProjectDebugger: More fun with GDB” http://www.ibm.com/developerworks/aix/library/au-gdb.html
“14.3.4. UsefulKernel gdb Macros” from “EmbeddedLinux Primer” http://book.opensourceproject.org.cn/embedded/embeddedprime/
gdb宏的使用
假设要使用下节的lsmod,该gdb宏能列举内核中的模块。 在内核源码目录下建立一个新文件lsmod,内容见下节。
装载宏
(gdb) source lsmod
查看说明
(gdb) help lsmod
list module struct's address, textaddress and their module name
使用
(gdb) lsmod
(gdb) lsmod
Address text Module
0xE014DDA0 0xE014D000 nls_iso8859_1
0xE0169AE0 0xE0164000 isofs
0xE014BA20 0xE0148000 zlib_inflate
0xE0161FE0 0xE0152000 udf
.....
0xE0012DE0 0xE000B000 processor
0xE0008EA0 0xE0008000 fan
0xE00223E0 0xE0020000 thermal_sys
----end----
(gdb)
(gdb)
我们查看一下processor模块结构体的内容
(gdb) p *(struct module *)0xE0012DE0
$10 = {
state = MODULE_STATE_LIVE,
list = {
next = 0xe0008ea4,
prev = 0xe0018984
},
name = "processor", '