[hellogcc] RE: [hellogcc] [投稿] 一个关于重定位的例子

  • From: 吴亚杰 <yajie.wu@xxxxxxxxxxx>
  • To: <hellogcc@xxxxxxxxxxxxx>
  • Date: Thu, 25 Aug 2011 06:24:42 +0000


MIPS ABI?     是哪个文档呢?可否告诉我

> Date: Wed, 24 Aug 2011 13:15:38 +0800
> Subject: [hellogcc] [投稿] 一个关于重定位的例子
> From: mingjie.xing@xxxxxxxxx
> To: hellogcc@xxxxxxxxxxxxx
> 
> 一个关于重定位的例子
> 
> 1、重定位项有两种结构类型,
> 
> typedef struct {
>   Elf32_Addr r_offset;
>   Elf32_Word r_info;
> } Elf32_Rel;
> 
> typedef struct {
>   Elf32_Addr r_offset;
>   Elf32_Word r_info;
>   Elf32_Sword r_addend;
> } Elf32_Rela;
> 
> MIPS是使用了第一种方式,所以,addend是存放在了将要被修改的位置,即需要进行重定位的地方。
> 
> 2、执行如下命令,
> 
> $ mipsel-linux-readelf -r sysconf.o
> 
> Relocation section '.rel.rodata' at offset 0xb74 contains 132 entries:
>  Offset     Info    Type            Sym.Value  Sym. Name
> 00000000  0000020c R_MIPS_GPREL32    00000000   .text
> 00000004  0000020c R_MIPS_GPREL32    00000000   .text
> 00000008  0000020c R_MIPS_GPREL32    00000000   .text
> 0000000c  0000020c R_MIPS_GPREL32    00000000   .text
> 00000010  0000020c R_MIPS_GPREL32    00000000   .text
> 
> 可以看到,除了.text段中有需要进行重定位的地方以外,.rodata中也有一些,并且这些offset是对应于.rodata段。
> 
> $ mipsel-linux-objdump -Dr sysconf.o
> 
> Disassembly of section .rodata:
> 
> 00000000 <.rodata>:
>    0:   ffffc064        0xffffc064
>                         0: R_MIPS_GPREL32       .text
>    4:   ffffc06c        0xffffc06c
>                         4: R_MIPS_GPREL32       .text
>    8:   ffffc074        0xffffc074
>                         8: R_MIPS_GPREL32       .text
>    c:   ffffc07c        0xffffc07c
>                         c: R_MIPS_GPREL32       .text
>   10:   ffffc084        0xffffc084
>                         10: R_MIPS_GPREL32      .text
> 
> 这里将.rodata中需要重定位的地方和对应的重定位项结合在一起打印出来。可以看出,对于.rodata中的第一个字,其保存的addend值为0xffffc064。
> 
> 3、MIPS ABI文档如下描述R_MIPS_GPREL_32:
> 
> Name                        Value    Field     Symbol       Calculation
> R_MIPS_GPREL_32    12    T-word32    local    A + S + GP0 - GP
> 
> A
>  Represents the addend used to compute the value of the relocatable
>  field.
> 
> S
>  Represents the value of the symbol whose index resides in the relocation
>  entry, unless the the symbol is STB_LOCAL and is of type
>  STT_SECTION in which case S represents the original sh_addr minus
>  the final sh_addr.
> 
> GP
>  Represents the final gp value to be used for the relocatable, executable,
>  or shared object file being produced.
> 
> GP0
>  Represents the gp value used to create the relocatable object.
> 
> $ mipsel-linux-objdump -Dr sysconf.o
> 
> Disassembly of section .reginfo:
> 
> 00000000 <.reginfo>:
>    0: b200001e        0xb200001e
>       ...
>   14: 00004000        sll     t0,zero,0x0
> 
> .reginfo段中记录了ri_gp_value,可以看到,GP0的值为0x4000。
> 
> 4、当链接成可执行程序时,依照同样的方法,我们可以找到
> 
> 00400094 <.reginfo>:
>   400094:       b20000f4        0xb20000f4
>         ...
>   4000a8:       10008a70        b       3e2a6c <__start-0x1d6a4>
> 
> 所以,gp的值为0x10008a70,
> 
> 00425c70 <__sysconf>:
>   425c70:       3c1c0fbe        lui     gp,0xfbe
> 
> 所以,S的值为0x425c70,
> 
> 根据公式“A + S + GP0 - GP”,可以计算出.rodata中需要重定位的地方的最终内容。比如,对于.rodata中的第一个字,
> 
> 0xffffc064 + 0x425c70 + 0x4000 - 0x10008a70 = 0xf041d264
> 
> 5、附注
> 
> 如果查看一下binutils/bfd/elf32-mips.c,就可以找到R_MIPS_GPREL32相应的HOWTO数据结构,以及处理函数。
> 
> 6、其它
> 
> 这里,我个人有一个地方没有搞明白,MIPS ABI中介绍说S是初始的sh_addr减去最终的sh_addr,但是,看起来,似乎应该反过来才正确。
> 
> 邢明杰
                                          

Other related posts: