2011年(15)
分类: 嵌入式
2011-12-19 12:01:12
Relax_type在输出目标文件时进行relax时所需要的信息,包括跳转的地址范围和目前地址长度,比如,6位偏移,然后左移两位,那么这个地址偏移可以表示前后128字节的地址,并且地址字节长度为1。这个类型主要使用在机器相关的处理,做移植工作的人员需要提供目标机器所对应的跳转类型,即relax表,便于relax的进行。
/* 该跳转向前可以跳转最大偏移 */ offsetT rlx_forward; /*该跳转向前可以跳转最大偏移*/ offsetT rlx_backward; /* 地址的字节长度(即表示该跳转地址的字节长度) */ unsigned char rlx_length; /* 是否还有需要relax,0为结束 */ relax_substateT rlx_more; |
union { //重定位之前 struct { symbolS *offset_sym; //偏移量 reloc_howto_type *howto; //重定位类型 symbolS *sym; //需要定位符号 bfd_vma addend; //基址 } a; //重定位之后 struct { asection *sec; //重定位从属的段 asymbol *s; //重定位符号 arelent r; //重定位信息入口 } b; } u; |
Reloc_list包含了重定位信息,包括重定位之前的信息收集(包括基址,偏移和重定位类型),和重定位之后信息(主要是arelent,即BFD中特殊的重定位入口类型)
/*是否是pc相对重定位 */ unsigned fx_pcrel : 1; /*是否为立即数偏移量 */ unsigned fx_im_disp : 2; /* 机器相关位,自己备用 */ unsigned fx_tcbit : 1; unsigned fx_tcbit2 : 1; /*是否经过重定位 */ unsigned fx_done : 1; /*是否取消溢出 */ unsigned fx_no_overflow : 1; /* 是否检查溢出 */ unsigned fx_signed : 1; /* pc相对偏移量 */ char fx_pcrel_adjust; /* fix需要多少字节数*/ unsigned char fx_size; /* 进行fix所对应的frag */ fragS *fx_frag; /* 要进行fix的起始地址 */ long fx_where; /*要增加的符号或符号链表 */ symbolS *fx_addsy; /*要去除的符号或符号链表 */ symbolS *fx_subsy; /*要增加的绝对偏移 */ valueT fx_offset; /*当前的dot地址(dot值是特殊的值,类似当前地址,用于计算实际fix后偏移) */ addressT fx_dot_value; /* 链表结构 */ struct fix *fx_next; /* 对bit调整,即少于1个字节的fix */ bit_fixS *fx_bit_fixP; //重定位类型(如何定位相对或者绝对,定位长度64 32等) bfd_reloc_code_real_type fx_r_type; |
Fix结构主要用于在输出目标文件期间,对未解析地址信息进行fix,而fix的信息,是有md_assemble中对于特定指令所生成的fix信息,链接到一个fix链表中,这个fix链表分别保存在frchain(frag的一个控制链表)和segment_info(段信息)中(后文介绍)。
/*位于目标文件的原始地址(字节偏移量)*/ addressT fr_address; /* 最后一遍relax后的地址 */ addressT last_fr_address; /* fix之后frag中的固定字节大小 */ offsetT fr_fix; /* 固定字节之后的字节大小 */ offsetT fr_var; /* 可变尾部的大小 */ offsetT fr_offset; /* 尾部可变符号(链表) */ symbolS *fr_symbol; /* opcode地址 */ char *fr_opcode; /* 构成链表结构 */ struct frag *fr_next; //下一条代码段 /* 是否跳过relax */ unsigned int relax_marker:1; /* 是否为空frag */ unsigned int has_code:1; /* 指令地址 */ unsigned int insn_addr:6; /* relax状态 */ relax_stateT fr_type; /* 这个也是relax状态,可以用于在机器相关处理的分类 */ relax_substateT fr_subtype; /* 代码片段所包含的二进制信息 */ char fr_literal[1]; |
Frag是GAS中基本的数据结构,它是基于汇编代码的最小结构,是最后构成目标输出文件的基本。可以看到,Frag包含了目前代码片段的起始地址和这些代码的二进制信息,而其余的信息,则是帮助该Frag进行relax和重定位。
struct frag *frch_root; /* frag头 */ struct frag *frch_last; /* frag尾 */ struct frchain *frch_next; /* 下一个frchain,构成链表 */ subsegT frch_subseg; /* 对应的subsegment */ fixS *fix_root; /* fix头 */ fixS *fix_tail; /* fix尾 */ struct obstack frch_obstack; /* 分配内存区,后文讲述 */ fragS *frch_frag_now; /* 当前的frag */ |
Frchain是frag的控制结构,可以看到,不仅包含所有对应的frag信息,还有当前操作的frag,同时,还有对应于这系列frag的fix信息。这些fix信息,分别保存在各自的frchain中,会在其后整理保存到相应的segment_info中。
上述几者关系如下图: