[转]GDBINT gdb internal Notes …

来源:互联网 发布:阿里云静态资源 编辑:程序博客网 时间:2024/06/09 07:37

Addinga New Target

为了建立一个target,需要添加以下文件:

gdb/config/arch/ttt.mt

     makefile,定义 `TDEPFILES=...' and `TDEPLIBS=...'. 指定`TM_FILE=tm-ttt.h':描述tty的头文件. 

 

 


gdb/ttt-tdep.c  或许根本就不需要这个文件.如果 `tm-ttt.h'太复杂,可以把函数放到这里

 


gdb/arch-tdep.c 
gdb/arch-tdep.h registers, stack ...的描述, it is included by`ttt-tdep.h'.

 

gdb/config/arch/tm-ttt.h`tm.h'是这个文件的一个link,configure自动创建,registers, stack frame formatinstructions描述.新的target不应该使用这个文件了.

 

`gdb/config/arch/tm-arch.h' 新target无需此文件了. 同cpu的target可以共享.

如果是为一个新的os添加支持(cpu已存在),则只需要添加`config/tm-os.h' ,描述此os的特殊facilities即可,比如extra symbol table info;the breakpoint instruction needed; 等等),然后写一个`arch/tm-os.h',就include`tm-arch.h'和config/tm-os.h即可.


TargetDescriptions 通过上一个章节,可以对target的各种特性有一个大致了解:寄存器,地址和指针,stackframe ...
Target DescriptionsImplementation

  GDB 连接到一个newtarget之前,恢复成一个默认的target,连接完成后,通过 target_find_description找到新的target. 新的target可以由用户指定的XML文件来获取,或者远程的qXfer:features:read (alsoXML), 或者在targetvector里定制的to_read_description函数来获取target.比如远程的target支持判断一个MIPStarget是32-bit还是64-bit(根据 `g' packet的大小).


  发现一个targetdescription后,GDB 通过gdbarch_update_p创建新的gdbarch. 优先根据`<architecture>'来确定调用那个 gdbarchinitialization函数.然后,调用初始化函数,初始化函数可以调整这个architecture:比如通过to_read_description确定属性集.


Adding Target DescribedRegister Support

Targetdescriptions通过体系特定的支持函数,可以报告更多的寄存器到target.

一个targetdescription或者没有寄存器,或者有完整的寄存器集.

如果 tdesc_has_registers 返回1,代表这个description包含寄存器,architecture's gdbarch_init函数应该完成如下功能:

 

  • 通过tdesc_data_alloc分配内存(在搜索匹配的gdbarch后者分配新的之前进行)

     

  • 通过tdesc_find_feature,根据name确定标准属性集.

     

  • 通过tdesc_numbered_register 和tdesc_numbered_register_choices 确定standard features需要的registers.

     

  • 如果需要的feature缺失,返回NULL, 如standardfeature缺失必要寄存器,返回NULL.

     

  • 释放分配的数据,除非调用了tdesc_use_registers.

     

  • Call set_gdbarch_num_regs asusual, with a number higher than any fixed number passed totdesc_numbered_register.

     

  • 返回新创建的gdbarch之前,调用tdesc_use_registers.

     

调用tdesc_use_registers后,这个architecture的register_name, register_type, 和 register_reggroup_proutines将不会被调用;这些信息将从target description获取. num_regs或许增加,因为可能有新的寄存器加进来.

Pseudo-registers require some extracare:

 

  • Using tdesc_numbered_registerallows the architecture to give constant register numbers tostandard architectural registers, e.g. as an enum in `arch-tdep.h'.But because pseudo-registers are always numbered above num_regs,which may be increased by the description, constant numbers can notbe used for pseudos. They must be numbered relative to num_regsinstead.

     

  • The description will not describepseudo-registers, so the architecture must callset_tdesc_pseudo_register_name, set_tdesc_pseudo_register_type, andset_tdesc_pseudo_register_reggroup_p to supply routines describingpseudo registers. These routines will be passed internal registernumbers, so the same routines used for the gdbarch equivalents areusually suitable.
下面是一个pseudo-register的例子:

http://sourceware.org/ml/gdb-patches/2000-07/msg00127.html


Target VectorDefinition  target vector定义GD对target system的抽象接口.GDB包含30-40这样的接口,但每个configuration只有几个.
Managing Execution State

  target vector状态:

completelyinactive :not pushed on the targetstack

active but not running:pushed, butnot connected to a fully manifested inferior

completelyactive (pushed, with an accessibleinferior).

persistent connections to a targeteven when the target has exited or not yet started.如:

使用targetsim连接到simulator是,并不创建进程,寄存器和内存在run前都不可访问.类似的,kill之后,程序也不能继续运行.但是这两种情况下GDB仍然连接到simulator.

如果target仅仅支持completeactivation,则在其to_open函数中,应该使用push_target将自己压入堆栈(rfc),在其to_mourn_inferior函数中通过unpush_target将自己出栈.

如果target支持partial和completeactivation,就不应该在to_mourn_inferior中出栈(但是仍然需要在to_open中入栈),而应调用target_mark_running或者target_mark_exited. 只要任何时候inferior fullyactive就应该调用target_mark_running(如在to_create_inferior和to_attach中),而inferior inactive(to_mourn_inferior)时就掉用target_mark_exited.在to_kill中,应该调用target_mourn_inferior确保target进入inactive状态.



Existing Targets

 

File Targets

executables 和 core files 都有targetvectors.

 


Standard Protocol and RemoteStubs

GDB 文件remote.c 通过串口和targetsystem通讯.GDB 提供一系列的stubs:stub集成到target系统中作为GDB的通讯断点.其名称一般是*-stub.c. 

  GDB user'smanual 描述如何将stub嵌入target中:下面的例子讨论集成SPARC stub 到操作系统:

stub中的trap处理代码假设trap_low的接口如下:

 

  1. %l1 和 %l2 分别包含pc 和 npc;

     

  2. traps 以禁止;

     

  3. 已经在正确的trap window(rfc).

满足以上条件时,可以从hw trapvector直接跳到stub.一般情况下stub使用的trap,操作系统是不使用的(一般是不可恢复性错误),也没有共享问题(有也可以支持).最重要的trap之一ta 1(rfc):用于单步执行或者breakpoint.

这里有个remote stub的参考文档:
http://sca.uwaterloo.ca/coldfire/gcc-doc/docs/porting_4.html 



Native Debugging

 

如下文件控制native support的配置:

 

`gdb/config/arch/xyz.mh' makefile. 通过NATDEPFILES列出所有体系相关的.o文件 . 通过NAT_FILE= nm-xyz.h指定nativesupport的头文件.其他可选项:`NAT_CFLAGS', `NAT_ADD_FILES', `NAT_CLIBS',`NAT_CDEPS'参考`Makefile.in'.

 

`gdb/config/arch/nm-xyz.h' `nm.h' 是到此文件的一个link(configure 自动创建).包含C的宏定义,描述native system环境,如child process control和corefile.

 

`gdb/xyz-nat.c' native support的C代码.(有些系统都没有这个).

许多通用函数可以为很多系统共享,如果你的系统可以使用这些函数,使用NATDEPFILES定义所需要的.o即可.否则,你需要重新实现这些函数,并放到xyz-nat.c中.

`inftarg.c' 包含 target_opsvector ,支持通过ptrache和wait的Unix childprocesses.

 

`procfs.c' target_opsvector 支持通过/proc控制Unix child processes.

 

`fork-child.c' unix形式的fork和exec创建子进程.

 

`infptrace.c' 采用unix ptrace接口的被调试程序控制. 
Native core fileSupport

 

`core-aout.c::fetch_core_registers()'读取corefile的registers. 此函数调用register_addr(). GDB使用BFD读取core file,事实上,所有machines都应该使用 core-aout.c, 仅提供fetch_core_registers即可(xyz-nat.c,or REGISTER_U_ADDR in nm-xyz.h).

 

`core-aout.c::register_addr()' 如果nm-xyz.hfile中定义了REGISTER_U_ADDR(addr, blockend, regno),其功能应该如下:将addr设置成'user' struct中GDB寄存器regno的偏移. blockend是'upgae'(u.u_ar0)内的偏移.如果定义了 REGISTER_U_ADDR , `core-aout.c'会定义register_addr() 函数,并使用这个宏.如果没有定义此宏,但是又要使用fetch_core_registers(),则必须自己定义 register_addr(), 并置于xyz-nat.c 如果自己定义了fetch_core_registers(), 就不用把register_addr()单独拿出来定义了.

当 在一个新的OS上运行GDBnative时,为了确保能够调试core file,就要写代码支持解析这个OS的corefile,或者修改`bfd/trad-core.c'. 首先,定义一个寄存器结构来描述OS Core file中的寄存器(比如corefile 的u-area),将定义core file header的头文件包含进来(u-area or a struct core).然后,修改trad_unix_core_file_p 使用这些信息建立core file总的data segment, stacksegment和其他段的信息(shared library ,control information), 以及"registers"segment(如果有两组寄存器,比如integer和float),即 "reg2" segment. 这些section的信息使BFD知道如何从corefile读取这些信息.然后,修改GDB:定义fetch_core_registers,使用通用的core-aout.c,或者自己的`xyz-nat.c'.GDB使用这个函数来将寄存器的值转移到GDB的"registers" array中.

   如果你的系统使用`/proc'控制进程,并使用ELFformat的core files,则可以使用相同的函数来读取进程和core file的寄存器.



 

NativeConditionals

`nm-system.h'中可能存在的configure:

 

CHILD_PREPARE_TO_STORE If the machine stores allregisters at once in the child process, then define this to ensurethat all values are correct. This usually entails a read from thechild.

[Note that this is incorrectlydefined in `xm-system.h' files currently.]

 

FETCH_INFERIOR_REGISTERS 如果自己定义fetch_inferior_registers 和store_inferior_registers ,定义此宏.否则`infptrace.c'将编译进来.

 

int gdbarch_fp0_regnum (gdbarch) 返回首个浮点寄存器的编号.

 

int gdbarch_get_longjmp_target (gdbarch) 在ECstation和Iris中,这个是一个native-dependent的参数,大多数系统是targetdependnet的.此函数确定longjmp将要跳转到的PC地址,(假定我们正好停在一个longjmpbrakpoint中).(see GDBINT)

 

I386_USE_GENERIC_WATCHPOINTS An x86-based machine can define thisto use the generic x86 watchpoint support; seeI386_USE_GENERIC_WATCHPOINTS.

 

ONE_PROCESS_WRITETEXT 定义此宏后,如果breakpoint插入失败,警告用户另一个进程可能使用同一个executable.

 

PROC_NAME_FMT 定义一个/proc设备的name格式.定义在`nm.h',覆盖`procfs.c'中的默认定义.

 

SHELL_COMMAND_CONCAT 启动inferior时,将此字符串作为shell命令的前缀.

 

SHELL_FILE 使用这个shell去启动inferior,默认是"/bin/sh".

 

SOLIB_ADD (filename, from_tty, targ,readsyms) 用于取filename中的symb到GDB的symbol table.如果 readsyms是0,symbols将不读入,但是其他处理照常进行.

 

SOLIB_CREATE_INFERIOR_HOOK (rfc) Define this to expandinto any shared-library-relocation code that you want to be runjust after the child process has been forked.

 

START_INFERIOR_TRAPS_EXPECTED 一般GDB启动一个inferior时,又两次trap:因此shell运行时,一次program 自己运行时.如果实际上不是2次,定义此宏为正确的值.

 

CLEAR_SOLIB See `objfiles.c'.

 

 



SupportLibrariesBFD

 

identifying executable and corefiles

 


access to sections offiles BFD 解析文件头,确定像.text .data这些section的名字,虚拟地址,大小等.

 

specialized core filesupport BFD 提供函数用于确定core file的failingsignal,以及此core file是否匹配一个特定的可执行文件.

 

locating the symbolinformation opcodes

广泛用于binutils.提供反汇编支持.

readline commandline编辑.

libiberty

此库提供一系列的函数用于补足,替换和扩展操作系统提供的功能.GDB使用很多这个库提供的特性:如 C++demangler,IEEE floating formatsupport, 输入选项解析`getopt', `obstack'扩展等.


obstacks in GDB

 obstack是一个内存分配和释放机制.每个 obstack 是一个内存池,操作方式类似堆栈.内存以LIFO方式在obstck上分配和释放.

主要用于object files管理.每个obj文件有一个对应的obstack,许多对象在obstack上分配:....(略)

 在不同时间分配的对象,一次性的释放.

 

gnu-regex

Regexconditionals. 

 

 


Array Containers

see `vec.h' (略)

例子:

DEF_VEC_P(tree); //non-managed tree vector.

struct my_struct {
VEC(tree) *v; // A (pointer to) a vector of treepointers.
};

struct my_struct *s;

if (VEC_length(tree, s-&gt;v)) { we have somecontents }
VEC_safe_push(tree, s-&gt;v, decl); // append somedecl onto the end
for (ix = 0; VEC_iterate(tree, s-&gt;v, ix, elt);ix++)
{ do something with elt }
其他接口函数:

 

 


 


 


 


 


VEC_length  VEC_empty VEC_last ....

 

Coding
Cleanups

Cleanups 是GDB使用的一个通用机制.cleanup会在以后的合适时间执行:命令完成,error处理等.

使用方式:

struct cleanup *old_chain;

     Declarea variable which will hold a cleanup chain handle.

 

old_chain = make_cleanup (function, arg); Make a cleanup which willcause function to be called with arg (a char *) later. The result,old_chain, is a handle that can later be passed to do_cleanups ordiscard_cleanups. Unless you are going to call do_cleanups ordiscard_cleanups, you can ignore the result from make_cleanup.

do_cleanups (old_chain); Do all cleanups added to the chain sincethe corresponding make_cleanup call was made.

discard_cleanups (old_chain); Same as do_cleanups except that itjust removes the cleanups from the chain and does not call thespecified functions. 细节请参考GDBINT.

Per-architecture moduledata

向gdbarch 添加module specificper-architecture data-pointers的机制:(see GDBINT)

Function: struct gdbarch_data *gdbarch_data_register_pre_init (gdbarch_data_pre_init_ftype*pre_init) pre_init is used to, on-demand,allocate an initial value for a per-architecture data-pointer usingthe architecture's obstack (passed in as a parameter). Sincepre_init can be called during architecture creation, it is notparameterized with the architecture. and must not call modules thatuse per-architecture data.

Function: struct gdbarch_data *gdbarch_data_register_post_init (gdbarch_data_post_init_ftype*post_init) post_init is used to obtain aninitial value for a per-architecturedata-pointer after. Since post_init is always calledafter architecture creation, it both receives the fully initializedarchitecture and is free to call modules that use per-architecturedata (care needs to be taken to ensure that those other modules donot try to call back to this module as that will create in cyclesin the initialization call graph).

These functions return a structgdbarch_data that is used to identify the per-architecturedata-pointer added for that module.

The per-architecture data-pointeris accessed using the function:

Function: void *gdbarch_data (structgdbarch *gdbarch, struct gdbarch_data*data_handle) Given the architecture arch andmodule data handle data_handle (returned bygdbarch_data_register_pre_init or gdbarch_data_register_post_init),this function returns the current value of the per-architecturedata-pointer. If the data pointer is NULL, it is first initializedby calling the corresponding pre_init or post_initmethod. 
Wrapping OutputLines

输出换行的标准. 细节参考GDBINT.



GDB Coding Standards以下部分请参考GDBINT.

ISO C

GDB assumes an ISO/IEC 9899:1990(a.k.a. ISO C90) compliant compiler.

GDB does not assume an ISO C orPOSIX compliant C library.

 

MemoryManagement

GDB does not use the functionsmalloc, realloc, calloc, free and asprintf.

GDB uses the functions xmalloc,xrealloc and xcalloc....


CompilerWarnings Formatting CommentsC Usage

FunctionPrototypes Internal Error RecoveryFile NamesInclude FilesClean Design and PortableImplementation

 GDB多年的经验告诉我们许多可移植性方面的问题:不能假定任何target的byteorder(values, object files, andinstructions).必须使用SWAP_TARGET_AND_HOST宏. 

所有操作target的函数必须使用 target_opsvector.不能假定host和target是同一台机器(除了native),尤其不能假定target机器的头文件可以在host上使用.

more detail see GDBINT


PortingGDB

在新的machine上编译GDB需要很多配置工作,需要修改许多头文件和配置脚本.假定新的host是xyz (e.g.,`sun4'), 其配置名是 arch-xvend-xos (e.g., `sparc-sun-sunos4') :

 

  • 在根目录,编辑 `config.sub' 添加 arch,xvend, and xos到architecture列表.添加xyz作为arch-xvend-xos的别名.运行以下命令测试修改:
    ./config.subxyz
    ./config.sub arch-xvend-xos
    (或许需要port BFD)
  • 配置GDB:编辑`gdb/configure.host'时期认识你的系统,设置 gdb_host 为 xyz,编辑`gdb/configure.tgt',设置gdb_target为合适值,如xyz.
  • 最后,开始写对应的host-,native-,  target-dependent的 `.h' 和 `.c'文件.......(不少啊).

 


Other

为完整性,以下部分没有阅读,这些部分描述GDB的代码配置管理部分内容,以及代码阅读的一些提示:

16. Versions and Branches

17. Start of New YearProcedure

18. Releasing GDB

19. Testsuite

20. Hints

A. GDB Currently availableobservers

B. GNU Free DocumentationLicense


转自:http://hi.baidu.com/systemsoftware/blog/item/7b33333d69cf9e0ebba16772.html

原创粉丝点击