[hellogcc] Re: [hellogcc] Re: [投稿] x86 ABI中PLT例子的翻译

  • From: Mingjie Xing <mingjie.xing@xxxxxxxxx>
  • To: hellogcc@xxxxxxxxxxxxx
  • Date: Mon, 14 May 2012 09:36:46 +0800

2012/5/13 Yao Qi <qiyaoltc@xxxxxxxxx>:
> 5 . Consequently, the program pushes a relocation offset (offset) on the 
> stack.
> The relocation offset is a 32-bit, non-negative byte offset into the 
> relocation
> table. The designated relocation entry will have type R_386_JMP_SLOT,
> and its offset will specify the global offset table entry used in the previous
> jmp instruction. The relocation entry also contains a symbol table index,
> thus telling the dynamic linker what symbol is being referenced, name1 in
> this case.
>
> 因此,程序将一个重定位偏移量(offset)压入栈中 (see the insn on 0x0804831e: push 
> 0x10)。重定位偏移量为一个32位,非负的,重定位表的字节偏移。其所指定的重定位项将具有R_386_JMP_SLOT类型,并且它的偏移量指定了在之前jmp指令中会用到的全局偏移表项。
>
> Relocation section '.rel.plt' at offset 0x2a0 contains 3 entries:
>  Offset     Info    Type            Sym.Value  Sym. Name
> 0804a000  00000107 R_386_JUMP_SLOT   00000000   __gmon_start__
> 0804a004  00000207 R_386_JUMP_SLOT   00000000   __libc_start_main
> 0804a008  00000307 R_386_JUMP_SLOT   00000000   puts
> 我们可以看到,这里有一个reloc R_386_JUMP_SLOT,对应的地址是0x804a008,其实就是 puts对应的 .got.plt 
> 的entry。
>
> 重定位项还包含了一个符号表索引,因此告诉了动态链接器哪个符号在被引用。在该例子中,为name1.
>
>
> 这里的offset (就是 0x10)还是不是很清楚,它什么是 puts在.rel.plt 段里边的那个记录的偏移吗?
> .rel.plt 段的大小是 0x16,里边包含三个一样类型的记录,那么第三个应该就是offset 0x10。
>
>    0x80482a0->0x80482b8 at 0x000002a0: .rel.plt ALLOC LOAD READONLY DATA 
> HAS_CONTENTS
>
> 这些是我的猜测。

正如你猜测的,这个offset(0x10)是指的.rel.plt段的偏移,也就是第三项

0804a008  00000307 R_386_JUMP_SLOT   00000000   puts

这里可以看出,.rel.plt的每一项是8个字节,我手中的这个ABI手册比较旧,没有对这个段和每一项的大小做介绍。

> 第二个问题,dynamic linker对R_386_JUMP_SLOT是怎么处理的,都干了些什么?

重定位项R_386_JUMP_SLOT包含了offset,info,type,symbol这些信息。其中offset(0x0804a008)指定了在之前jmp指令中会用到的全局偏移表项,symbol信息告诉动态链接器哪个符号在被引用。动态链接器要做的事情就是将这个符号的实际值(即name1的值)填写到偏移量为0x0804a008的全局偏移表项中,即更新name1的全局偏移表项。

> 6 . After pushing the relocation offset, the program then jumps to .PLT0, the
> first entry in the procedure linkage table. The pushl instruction places the
> value of the second global offset table entry (got_plus_4 or 4(%ebx)) on the
> stack, thus giving the dynamic linker one word of identifying information.
> The program then jumps to the address in the third global offset table entry
> (got_plus_8 or 8(%ebx)), which transfers control to the dynamic linker.
>
> 在压入重定位偏移量之后,程序然后跳转到.PLT0,过程链接表的第一项。
>
>   0x08048323 <puts@plt+11>:    jmp    0x80482e8  // jump to start of .plt 
> section.
>
> .PLT0:
>   0x080482e8:  pushl  0x8049ff8
>   0x080482ee:  jmp    *0x8049ffc
>
> pushl指令将全局偏移表的第二个表项(got_plus_4 or 4(%ebx))压入栈中,因此给了动态链接器一个字的标识信息。
>           ^^^^^^^^^^
> it should be the 2nd entry of .got.plt,
>   0x8049ff4->0x804a00c at 0x00000ff4: .got.plt ALLOC LOAD DATA HAS_CONTENTS
>
> 程序然后跳转到全局偏移表的第三个表项中(got_plus_8 or 8(%ebx))的地址,其将控制转换给动态链接器。
>              ^^^^^^^^^ .got.plt, isn't?

这个ABI文档是旧的,所以实际情况下这里应该是.got.plt,关于为什么从最初的.got分离出.got.plt,参见http://sourceware.org/ml/binutils/2004-03/msg00350.html

谢谢
邢明杰

Other related posts: