Chinaunix首页 | 论坛 | 博客
  • 博客访问: 370314
  • 博文数量: 64
  • 博客积分: 2975
  • 博客等级: 少校
  • 技术积分: 831
  • 用 户 组: 普通用户
  • 注册时间: 2007-01-14 10:59
文章存档

2014年(2)

2012年(7)

2010年(40)

2009年(5)

2008年(8)

2007年(2)

分类: LINUX

2008-12-08 11:03:07

总结
R_386_NONE        0    none    none
1.ld时重定位
1.1位置相关
1.1.1 R_386_32
R_386_32     1    word32  S + A //数据,绝对地址
符号的值即变量的地址,因此变量都需要重定位
如果变量的值是普通值,则不需对值重定位
如果变量的值是地址,则需对值重定位,例如char *="abc";
Offset    Info  Type            Symbol's Value  Symbol's Name
0000000b  00301 R_386_32              00000000  .data          
00000010  00e02 R_386_PC32            00000000  printf  
   9:   ff 35 00 00 00 00       pushl  0x0 //ff 35 将立即数压栈
   f:   e8 fc ff ff ff          call   10 //e8 相对寻址
  14:   83 c4 10                add    $0x10,%esp
所以R_386_32都是对Offset处的地址值重定位
S即调整后的符号值(新的变量地址),A即原值(Offset处的地址值,需要重定位的地址)
1.1.2 R_386_PC32
R_386_PC32     2    word32  S + A - P//代码,相对地址
P即Offset
连接时,ld会合并相同的节,假设printf被安排的地址是x,1.o中.text节安排的地址是y
则x+(-4)-(y+10)=x-y-14,所以重定位的结果是x-y-14,
当cpu执行y+f:处的call指令时,ip指向y+14,则call的目标地址是ip+(x-y-14)=x
1.2 位置无关(PIC)
1.2.1 R_386_GOTPC
R_386_GOTPC    10    word32  GOT + A - P
GOT即GOT地址(符号_GLOBAL_OFFSET_TABLE_的值),A为Offset处值,P为Offset.
 Offset    Info  Type            Symbol's Value  Symbol's Name
  0000000f  00e0a R_386_GOTPC           00000000  _GLOBAL_OFFSET_TABLE_   
  00000018  00309 R_386_GOTOFF          00000000  .data                   
  0000001d  00f04 R_386_PLT32           00000000  printf                  
   7:   e8 00 00 00 00          call   c
   c:   5b                      pop    %ebx
   d:   81 c3 03 00 00 00       add    $0x3,%ebx
  13:   83 ec 0c                sub    $0xc,%esp
  16:   ff b3 00 00 00 00       pushl  0x0(%ebx)
  1c:   e8 fc ff ff ff          call   1d
        call    .L3
.L3:
        popl    %ebx
        addl    $_GLOBAL_OFFSET_TABLE_+[.-.L3], %ebx
        subl    $12, %esp
        pushl   )
        call   
1.2.2 R_386_GOTOFF
R_386_GOTOFF     9    word32  S + A - GOT//静态(局部)变量
将符号地址和GOT地址差值加上Offset处值存入Offset处.
1.2.3 R_386_GOT32
R_386_GOT32     3    word32  G + A - P//外部(全局)变量
G为符号在GOT中地址,A为Offset处值,P为Offset
1.2.4 R_386_PLT32
R_386_PLT32     4    word32  L + A - P//代码
L为符号在plt中的地址,A为Offset处值,P为Offset
2.执行时重定位
2.1 位置相关
2.1.1 R_386_32
2.1.2 R_386_PC32
2.2 位置无关
2.2.1 R_386_RELATIVE
R_386_RELATIVE    8    word32  B + A//局部变量
使用加载地址+Offset处值来重定位
Relocation section '.rel.dyn' at offset 0x330 contains 3 entries:
  Offset    Info  Type            Symbol's Value  Symbol's Name
  000013e8  00008 R_386_RELATIVE    //字符串地址  
  000013ec  00008 R_386_RELATIVE    //字符串地址
  00001408  01006 R_386_GLOB_DAT        000013ec  t                       
2.2.2 R_386_GLOB_DAT
R_386_GLOB_DAT    6    word32  S //外部全局在PIC so间共享,或PIC so共享可执行文件中的变量
S为调整后的符号值写入Offset处
对于本地全局变量,直接把调整后的符号值写入本地GOT
 3b6:   8b 83 10 00 00 00       mov    0x10(%ebx),%eax//%eax中地址值指向.data节
 3bc:   ff 30                   pushl  (%eax)//将.data节中的变量值入栈
对于外部全局变量,解析该符号值(即变量地址),写入本地GOT<<<<<
2.2.3 R_386_COPY
R_386_COPY     5    none    none//外部全局变量
可执行文件共享PIC so中变量,
由于所有的可执行文件都不需要重定位,所以为可执行文件共享动态
链接库中的全局变量单独设置这个属性,在本地的bss中分配空间,置
R_386_COPY定位类型,而不使用R_386_32定位类型(那样需使代码段可写,
且COW,耗费内存)
6.c
extern char * s;
extern int t;
1.c
char *s="abc";
int t=1;
6.o中
Relocation section '.rel.text' at offset 0x38c contains 5 entries:
  Offset    Info  Type            Symbol's Value  Symbol's Name
  0000000b  00901 R_386_32              00000000  s                       
  00000010  00a02 R_386_PC32            00000000  printf                  
  00000019  00b01 R_386_32              00000000  t                       
  0000001e  00c02 R_386_PC32            00000000  g                       
  00000024  00d01 R_386_32              00000004  u
Symbol table '.symtab' contains 14 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
     9: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND s
    10: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND printf
    11: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND t
    12: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND g
    13: 00000004     4 OBJECT  GLOBAL DEFAULT  COM u

gcc 1.so 6.o -o 6
而可执行文件6中就变成了
Relocation section '.rel.dyn' at offset 0x3f4 contains 3 entries:
  Offset    Info  Type            Symbol's Value  Symbol's Name
  080496b0  01006 R_386_GLOB_DAT        00000000  __gmon_start__          
  08049784  00105 R_386_COPY            08049784  t                       
  08049788  00905 R_386_COPY            08049788  s
    1: 08049784     4 OBJECT  GLOBAL DEFAULT   22 t
    9: 08049788     4 OBJECT  GLOBAL DEFAULT   22 s
可见s,t的Ndx不是UND,而是位于.bss中
将解析到的符号地址处的值(大小由size决定)复制到Offset处。
而同时so的GOT中该变量的地址值被改写成可执行文件中的地址
R_386_COPY read a string of bytes from the "symbol" address
and deposit a copy into this dword; the "symbol" object
contains the length; this is used to copy initialized data
from a library to the main app data space
 On i386 the most important ones are the R_386_COPY type,
 meaning "just copy the address of the symbol to that address"

2.2.4 R_386_JMP_SLOT
R_386_JMP_SLOT    7    word32  S//代码

其他:
1.如果文件使用了动态链接库,则该文件就有GOT
2.GOT中的信息
[root@proxy ~/3]# objdump -sj .got 6  
6:     file format elf32-i386
Contents of section .got:
 804968c b4960408 00000000 00000000 6a840408  ............j...
 804969c 7a840408 8a840408 9a840408 aa840408  z...............
 80496ac ba840408 00000000  
GOT[0]是.dynsym节的地址 
[20] .dynamic          DYNAMIC         080496b4 0006b4 0000d0 08  WA  5   0  4
GOT[1]是动态链接库自身的struct link_map*的指针
GOT[2]是_dl_runtime_resolve的地址
GOT[3]..,函数 解析前指向.plt中,解析后执行真正的函数地址
变量加载时解析,指向全局变量地址
3.plt
位置相关:
08048454 <.plt>:
 8048454:       ff 35 90 96 04 08       pushl  0x8049690
 804845a:       ff 25 94 96 04 08       jmp    *0x8049694
 8048460:       00 00                   add    %al,(%eax)
 8048462:       00 00                   add    %al,(%eax)
 8048464:       ff 25 98 96 04 08       jmp    *0x8049698
 804846a:       68 00 00 00 00          push   $0x0
 804846f:       e9 e0 ff ff ff          jmp    8048454 <_init+0x18>
 8048474:       ff 25 9c 96 04 08       jmp    *0x804969c
 804847a:       68 08 00 00 00          push   $0x8
 804847f:       e9 d0 ff ff ff          jmp    8048454 <_init+0x18>
 8048484:       ff 25 a0 96 04 08       jmp    *0x80496a0
PIC:
00000370 <.plt>:
 370:   ff b3 04 00 00 00       pushl  0x4(%ebx)
 376:   ff a3 08 00 00 00       jmp    *0x8(%ebx)
 37c:   00 00                   add    %al,(%eax)
 37e:   00 00                   add    %al,(%eax)
 380:   ff a3 0c 00 00 00       jmp    *0xc(%ebx)
 386:   68 00 00 00 00          push   $0x0
 38b:   e9 e0 ff ff ff          jmp    370
其中push $0x0是符号在rel节中的索引数0(字节偏移)
 
阅读(2424) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~