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

  • From: asmwarrior <asmwarrior@xxxxxxxxx>
  • To: hellogcc@xxxxxxxxxxxxx
  • Date: Thu, 10 May 2012 15:14:19 +0800

On 2012-5-9 12:30, Mingjie Xing wrote:
原文摘自SYSTEM V APPLICATION BINARY INTERFACE。

Figure 5-7: Position-Independent Procedure Linkage Table

.PLT0: pushl  4(%ebx)
             jmp    *8(%ebx)
             nop; nop
             nop; nop
.PLT1: jmp    *name1@GOT(%ebx)
            pushl  $offset
            jmp    .PLT0@PC
.PLT2: jmp    *name2@GOT(%ebx)
            pushl $offset
            jmp    .PLT0@PC
...

Following the steps below, the dynamic linker and the program ‘‘cooperate’’ to
resolve symbolic references through the procedure linkage table and the global
offset table.

动态链接器和程序,按照下面的步骤,协作完成对通过过程链接表和全局偏移表进行符号引用的解析。


1 . When first creating the memory image of the program, the dynamic linker
sets the second and the third entries in the global offset table to special
values. Steps below explain more about these values.

动态链接器在开始创建程序的内存映像时,会将全局偏移表中的第二,三项设置为特定的值。这些值在下面的步骤中详细解释。

2 . If the procedure linkage table is position-independent, the address of the
global offset table must reside in %ebx. Each shared object file in the pro-
cess image has its own procedure linkage table, and control transfers to a
procedure linkage table entry only from within the same object file. Conse-
quently, the calling function is responsible for setting the global offset table
base register before calling the procedure linkage table entry.

如果过程链接表是位置无关的,则全局偏移表的地址必须存在%ebx中。进程映像中的每个共享目标文件都有自己的过程链接表,并且只能从同一个目标文件中才能将控制转换到过程链接表的表项。因此,调用函数需要在调用过程链接表项之前,设置全局偏移表的基础寄存器。

3 . For illustration, assume the program calls name1, which transfers control to
the label .PLT1.

例如,假设程序调用了name1,其将控制转换到标号.PLT1.

4 . The first instruction jumps to the address in the global offset
table entry for
name1. Initially, the global offset table holds the address of the following
pushl instruction, not the real address of name1.

第一条指令跳转到全局偏移表项中name1的地址。初始的时候,全局偏移表中存放的是pushl指令之后的地址,而不是name1的实际地址。

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)压入栈中。重定位偏移量为一个32位,非负的,重定位表的字节偏移。其所指定的重定位项将具有R_386_JMP_SLOT类型,并且它的偏移量指定了在之前jmp指令中会用到的全局偏移表项。重定位项还包含了一个符号表索引,因此告诉了动态链接器哪个符号在被引用。在该例子中,为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,过程链接表的第一项。pushl指令将全局偏移表的第二个表项(got_plus_4 or
4(%ebx))压入栈中,因此给了动态链接器一个字的标识信息。程序然后跳转到全局偏移表的第三个表项中(got_plus_8 or
8(%ebx))的地址,其将控制转换给动态链接器。

7 . When the dynamic linker receives control, it unwinds the stack, looks at the
designated relocation entry, finds the symbol’s value, stores the ‘‘real’’
address for name1 in its global offset table entry, and transfers control to the
desired destination.

当动态链接器获得控制之后,其展开栈,查看指定的重定位项,发现符号的值,将name1的“实际”地址存放在它的全局偏移表项中,然后将控制转换到所希望的目的地。

8 . Subsequent executions of the procedure linkage table entry will transfer
directly to name1, without calling the dynamic linker a second time. That
is, the jmp instruction at .PLT1 will transfer to name1, instead of ‘‘falling
through’’ to the pushl instruction.

以后对过程链接表项的执行,将会直接转换到name1,而不需要再次调用动态链接器。也就是说,在.PLT1中的jmp指令会直接跳转到name1,而不会顺序执行到pushl指令。
这个帖子很好,讲解的很具体了。可惜我初看一遍,还是没看懂,呵呵,自己学识太浅了。。

Other related posts: