RSS
热门关键字:
当前位置 :| 主页>新手入门>

GDB/ARMulator介绍

来源:互联网 作者:teawater@hotmail.com 时间:2008-12-10 Tag:GDB/ARMulator   点击:

1.GDB/ARMulator基本介绍
GDB/ARMulator是GDB自带的一个Armulator(ARM模拟器,实际上应该是有不止一个软件包含这个功能,例如ADS,他们都叫Armulator),不过我查看GDB的源代码都是对ARM6的模拟,而现在比较常见的是打过uclinux开发组patch的GDB/ARMulator,这样这个模拟器主要就是对Atmel AT91扳进行了模拟,更多的信息可以到下面的URL去看。
http://www.uclinux.org/pub/uClinux/utilities/armulator/



2.GDB/ARMulator编译安装和基本使用
2.1.编译安装
如果我记得不错的话,在uclinux网站提供的arm工具链中的GDB就是打过patch的版本,你可以直接使用其。不过因为在下面要通过GDB调试的方式来帮助阅读其代码,所以在这里我决定是编译一个。
首先是在上面提到的地址下载到GDB代码以及patch,然后:
tar vxjf gdb-5.0.tar.bz2
gunzip < gdb-5.0-uclinux-armulator-20021127.patch.gz | patch -p0
cd gdb-5.0
./configure --target=arm-elf --prefix=/usr/local --without-gtk-prefix --without-gtk-exec-prefix --disable-gtktest
make
make install


2.2.基本使用
将你做好的文件系统镜象文件改名为boot.rom(这个文件和下面用的linux.2.4.x文件都可以在上面提到的地址下到),做软连接也可以,然后在这个目录中:
arm-elf-gdb linux.2.4.x
target sim
load
run
这样你就能看见uclinux在模拟器上跑起来了。



3.GDB/ARMulator代码阅读记录
GDB相关的代码很多,跟ARMulator相关的代码也不少,所以代码的阅读主要是跟着刚才跑通起uclinux使用的命令涉及的代码,其中很多地方都是用gba调试arm-elf-gdb的方式帮助阅读。


3.1.arm-elf-gdb linux.2.4.x

3.1.1.对sim的初始化
因为sim是作为gdb的一个target(应该可以称为调试目标吧 呵呵)存在的,所以在gdb运行的时候,要先对这个target进行初始化。在remote-sim.c文件中的函数_initialize_remote_sim就是对这个target的初始化函数,而这个函数将在启动的时候被调用。在这个函数中有3个操作:
第1个操作,调用init_gdbsim_ops函数,这个函数用来初始化全局结构变量gdbsim_ops,其的结构类型是target_ops,每个gdb中的target都有这么一个结构,这个结构定义在target.h文件中。这个变量的作用就是当调试开始的时候,gdb可以通过结构找到相应的对target进行控制的函数。
第2个操作,调用add_target将前面初始化好的gdbsim_ops增加到target_structs中用来方便系统对这个结构的使用。
第3个操作,用add_com给gdb增加了一个命令sim,这个命令通过调用sim_do_command这个函数可以帮助实现向sim发送命令,这个功能将在后面进行一次实际的应用,在那再详细介绍。
还有一点比较重要,sim目录下包含了很多cpu相关的目录,其中就就有arm目录,这就是最基本的ARMulator的代码,gdb对ARMulator的控制就是通过target的接口函数调用ARMulator的函数来完成的。

3.1.2.对linux.2.4.x的读入
因为这个读入的操作跟使用命令file进行读入是基本一样的,所以对file命令的过程进行分析。
在用户执行file命令后,将调用exec.c文件中的函数file_command。在这个函数调用的函数exec_file_command用来将可执行文件打开,在其中target_preopen函数会检查前面是否有文件打开执行等等,并向用户提问是否进行清除,exec_file_attach则是具体的打开文件的操作,在这里打开了一个可执行文件结构exec_bfd,这将在后面被用到。symbol_file_command函数用来将符号表等进行初始化。
而在启动对可执行文件的读入在main.c文件中的函数captured_main对exec_file_command和symbol_file_command进行了调用。


3.2.target sim
在这里主要完成对sim的初始化的工作,这些工作是通过调用remote-sim.c文件中的函数gdbsim_open函数来完成的。
在开始的时候初始化了一些参数,然后传递给了wrapper.c文件中的sim_open函数,在这里设置了ARMulator的引点以及一些其他的东西。
而后调用函数push_target将gdbsim_ops增加到target_stack列表上相应的层次上,当然具体这步的意义我还不是很清晰。

最后用参数-1调用了gdbsim_fetch_register函数,当这个函数的参数为-1的时候,将以参数0到15调用这个函数,代表对arm的16个寄存器的初始化。
在这些调用的时候只做了简单的检查就调用了wrapper.c中的函数sim_fetch_register,在这个函数中第一步是调用函数init,这个函数中进行了大部分的ARMulator初始化工作。

在init函数中可以看到定义了一个static变量done,用来保证初始化只进行一次。ARMul_EmulateInit函数对ARMul_ImmedTable和ARMul_BitList,不过我没能看出这2个东西的具体作用。

ARMul_NewState函数对保存着Armulator的所有方面状态的state进行了空间分配和其中元素中的初始化,具体每个元素的定义可以看armdefs.h对ARMul_State定义中的每个元素的注释,写的很明确。在这个函数最后调用了函数ARMul_Reset,这里是对state的进一步的初始化。
在ARMul_Reset函数最开始的部分是根据state->prog32Sig也就是系统模式是否用32位模式,来设置Reg[15]和Cpsr(在26位模式中cpsr在r15中),在其后调用的函数ARMul_CPSRAltered是在修改过Cpsr后对state中其他参数值进行更新的函数。
在后面调用的mmu_reset是对state->mmu中内容进行初始化的函数。
其后是mem_reset函数,其主要作用是对state->mem也就是ARMulator中的内存进行初始化,其中还包括了将相应的文件系统内存镜象(也就是内个boot.rom)读入内存的过程,这些要做的工作都是根据全局结构数组mem_banks的值来进行的。具体是根据数组mem_banks中元素的数量来对内存进行循环的初始化,第一部是根据mem_banks元素中相应长度指定mem.rom_size中相应元素的长度并给指针mem.rom分配内存,这样就分配了内存块,如果在mem_banks的元素中filename不为空,则就将文件打开并根据big_endian进行处理后写入内存块中。这个mem_banks实际上并不单纯是在初始化的使用,在Armulator实际运行中,对内存进行读写的时候,也会根据读写的地址查找相应的其中的元素,使用这个元素中指定好的读写函数。这里提到的内存可以参看armmem.c文件。

最新评论共有 0 位网友发表了评论
发表评论
评论内容:不能超过250字,需审核,请自觉遵守互联网相关政策法规。
用户名: 密码:
匿名?
注册

_×
嵌入式linux中文站
QQ群讨论 微博订阅

微信扫一扫关注我们
随时获取最新开源资讯