| teawater's profile冒充另类PhotosBlogLists | Help |
|
4/3/2006 移植GDB(3) init.c和target_ops v0.0 (更新时间:2006-02-27)http://www.linuxforum.net/forum/showthreaded.php?Cat=&Board=program&Number=596941 附件中有txt版本 需要登陆后才能看见 移植GDB(3) init.c和target_ops v0.0 teawater<teawater@gmail.com> 转载请标明来自 http://www.linuxforum.net 修改记录: v0.0 2006-02-27,v0.0版本编写完成。没有对target_ops结构的每个元素进行详细介绍。 2006-02-07,文档创建。 目录 1.写在前面 2.GDB/gdb/init.c 2.struct target_ops 3.struct target_ops current_target 3.1.概述 3.2.本地调试接口的装载 1.写在前面 本文针对GDB-6.3进行编写。 下面是本文将使用的缩写: GDBINT GDB Internals Manual的缩写。 GDB 指GDB源文件目录。 ARCH 体系结构名称。 TARGET 体系结构下的调试目标,一般是一种操作系统,比如Linux。 2.GDB/gdb/init.c 这个文件是在编译的时候动态生成的,具体生成的位置在/GDB/gdb/Makefile.in的1075行开始的代码,这个文件会在configure的时候作为模板生成/GDB/gdb/Makefile,那段生成init.c的代码就会在make的时候被调用。 这段生成init.c的代码主要的过程就是扫描所有编译中指定的库文件,比如指定在“移植GDB(1)”TARGET.mt文件和“移植GDB(2)”TARGET.mh文件的库文件,然后找出其中_initialize_NAME(后面的NAME可以是任意名称)为名称的函数,在init.c文件中生成一个函数initialize_all_files,对每个_initialize_NAME进行调用。 这个initialize_all_files函数将被GDB初始化函数GDB/gdb/top.c:gdb_init调用,也就是每次GDB初始化的时候都会对其进行调用。 所以库文件就可以通过包含一个_initialize_NAME名字的文件来进行一些初始化的操作,比如在“移植GDB(1)5.2”就介绍了在_initialize_ARCH_tdep函数中调用gdbarch_register函数注册gdbarch,下面将介绍的target_ops大部分也都是通过_initialize_NAME函数进行初始化和注册的。 2.struct target_ops struct target_ops定义在GDB/gdb/target.h文件中,GDB中所有被调试的目标的控制和访问函数都被封装成这个结构,然后根据需要将结构装载到current_target上(后面会详细介绍),当GDB调试的时候直接对current_target结构中的函数指针进行调用就可以。比如GDB的模拟功能sim、远程调试功能remote以及本地调试接口ptrace、procfs等都以target_ops结构封装的。 大部分的target_ops结构都是先在前面介绍过的_initialize_NAME函数中进行初始化,然后调用函数GDB/gdb/target.c:add_target注册到列表GDB/gdb/target.c:target_structs上。 3.struct target_ops current_target 3.1.概述 这个结构就是GDB用来控制当前被调试目标的结构,当系统初始化(设置为dummy_target)、读入可执行文件(设置为exec_ops)或者执行target命令以后,就会调用GDB/gdb/target.c:push_target函数将需要的target_ops结构初始化到current_target上。当调用一些GDB命令的时候,则会调用current_target中的函数指针,也就对被调试目标进行了调试。 3.2.本地调试接口的装载 因为这个.本地调试接口的装载过程不是很直接,所以在这里对其进行一些介绍。 第一步,在GDB读入可执行文件的时候,会自动将GDB/gdb/exec.c:exec_ops装载到current_target上。 第一步,当运行运行run的时候会调用GDB/gdb/infcmd.c:run_command函数,在这个函数进行了一系列的分析处理后,最后会调用GDB/gdb/target.h:target_create_inferior宏,这个宏调用current_target.to_create_inferior,这里将调用注册在exec_ops上的函数GDB/gdb/target.c:find_default_create_inferior。 第二步,find_default_create_inferior函数首先调用函数GDB/gdb/target.c:find_default_run_target,在这个函数将通过前面介绍过的target_structs列表,扫描每个用add_target注册的target_ops结构。先检查这个target_ops结构有没有注册to_can_run函数指针,如果有对这个函数指针进行调用,一般来说本地调试结接口的target_ops结构都会注册这个函数指针,而且函数都会返回1,而非本地调试接口的target_ops结构则不会,所以都返回真的时候就记录这个target_ops结构在指针runable上,同时给count加1。 最后在扫描结束的时候检查count是否为1,不为1则报错,所以建议一个TARGET中只包含一个本地调试接口,最后返回runable。 第三步,然后调用这个返回的target_ops结构的to_create_inferior,这里会将这个调试接口的target_ops结构初始化到current_target上。比如在GDB/gdb/inftarg.c:child_create_inferior就调用了GDB/gdb/inftarg.c:ptrace_him,ptrace_him第一步工作就是调用push_target将deprecated_child_ops装载到current_target上。 Comments (2)
TrackbacksThe trackback URL for this entry is: http://teawater.spaces.live.com/blog/cns!48DDFFCE89F7F319!1357.trak Weblogs that reference this entry
|
|
|