Chinaunix首页 | 论坛 | 博客
  • 博客访问: 60310
  • 博文数量: 15
  • 博客积分: 353
  • 博客等级: 一等列兵
  • 技术积分: 175
  • 用 户 组: 普通用户
  • 注册时间: 2011-12-12 16:15
文章分类
文章存档

2011年(15)

我的朋友

分类: 嵌入式

2011-12-23 17:12:42

Linux中的重定位处理都是通过bfd库完成的。本文描述的是在编译链接时bfd的重定位处理,不涉及运行时加载器的重定位。重定位信息保存在.rel.text节中,用“objdump -r ”可以查看。

1、重定位的流程:

重定位的过程是基于bfd_perform_relocation,各后端有不同的实现。这里以elf_backend_relocate_section分析:

//重定位处理开始
//符号重定位计算
if(common_section)relocation=0
else relocation=symbol->value
relocation+= symbol->section->output_offset
if(!(output_bfd&&!partial_inplace) ) relocation+=symbol->section->output_section->vma;

//最终连接重定位
relocation+=reloc_entry->addend
if(pc_relative)
  //relocation是要跳转到的新地址。
  //现在,relocation是绝对地址。
relocation-=input_section->output_section->vma + input_section->output_offset
  //现在,relocation是相对于节开头的偏移。
  if(pcrel_offset) relocation-=reloc_entry->address
  //现在,relocation是相对于PC的偏移。
endif

//perform_relocation特有的部分
if(!output_bfd)
reloc_entry->addend=relocation
reloc_entry->address+=input_section->output_offset
if(!partial_inplace)return
else
  reloc_entry->addend=0
endif

//重定位目标内容
x=read_content //从被定位的目标地址读取数据
x=(x&~dsk_mask)|( (x&src_mask+relocation>>rightshift<write_content(x)
//重定位处理结束

2、

本地符号辨别规则:[ (rela).r_info>>8 ] < (section header).sh_info

否则为全局符号。

处理方法的区别:

全局符号结构复杂(通过链表寻找);

全局符号只对defined和defweak进行处理,作出unresolved的标记,或与本地符号做完全相同的计算。

本地符号和全局符号的重定位计算方式是一模一样的。本地符号在链接时最终重定位后会被解析,但全局符号有可能被解析,有可能继续保留,特别是与动态连接相关的符号。

 

结构的作用

Howto结构保存重定位参数信息,供多个函数使用。

以RELA重定位为例,在重定位流程中,重定位内容是这样计算的:

x=(x&~dsk_mask)|( (x&src_mask+relocation>>rightshift<

下面的表格展示了该表达式的意义。

注:粗体字是howto结构的成员。

relocation

RRRRRRR

 

new_relocation=

relocation >>rightshift<<bitpos

000RRR0

 

x

IIINNNN

重定位前的指令

src_mask

0001110

指出操作数中参与累加的部分

dst_mask

0001111

指出指令中会受重定位影响的部分

p0=x&~dst_mask

III0000

操作码

p1= x&src_mask

000NNN0

操作数中参与累加的部分

p1

+

new_relocation

=

p2

000NNN0

+

000RRR0

=

00xxxx0

重定位的计算

p3=p2&dst_mask

000xxx0

 

x=p0|p3

IIIxxx0

重定位后的指令

阅读(2188) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~