目前我试图更接近汇编程序编程,因此查看了一个简单的hello world程序的汇编代码:
#include <stdio.h>
int main ()
{
int i;
for(i=0; i<10; i++)
{
printf("Hello, world!\n");
}
return 0;
}
现在我尝试了解fiew简单汇编程序命令如何工作,同时逐步完成汇编程序代码并分析究竟发生了什么:
0x000000000040052d <+0>: push rbp
0x000000000040052e <+1>: mov rbp,rsp
0x0000000000400531 <+4>: sub rsp,0x10
0x0000000000400535 <+8>: mov DWORD PTR [rbp-0x4],0x0
0x000000000040053c <+15>: jmp 0x40054c <main+31>
0x000000000040053e <+17>: mov edi,0x4005e4
0x0000000000400543 <+22>: call 0x400410 <puts@plt>
0x0000000000400548 <+27>: add DWORD PTR [rbp-0x4],0x1
0x000000000040054c <+31>: cmp DWORD PTR [rbp-0x4],0x9
0x0000000000400550 <+35>: jle 0x40053e <main+17>
0x0000000000400552 <+37>: mov eax,0x0
0x0000000000400557 <+42>: leave
0x0000000000400558 <+43>: ret
问题是我真的不明白这一行:
0x0000000000400543 <+22>: call 0x400410 <puts@plt>
我尝试以各种方式查看地址0x400410,但我真的不知道它真正做到了什么:/我也不知道这究竟意味着什么:<puts@plt>
如果有人能帮助我理解这条特定的路线,那会非常棒:) 问候困了
答案 0 :(得分:17)
PLT表示程序链接表。这是ELF文件中使用的一种特殊技术,用于在可以进行相对寻址的机器上本地化加载时进行修复。
您正在调用的函数位于另一个模块中(通常是libc.so. x ),因此在加载程序执行时必须提供函数的实际地址
PLT本质上是可执行文件(或.so文件)中的一个区域,其中所有未完成的引用都被收集在一起。它们具有目标机器的跳转指令形式,实际地址仍未填充。填充地址取决于加载程序。这个过程叫做修复。
因为模块的剩余部分使用相对寻址通过PLT进行函数调用,并且在链接时已知PLT的偏移量,所以不需要在那里修复任何内容。这意味着您的大多数模块可能会继续映射到模块文件而不是交换文件。
还需要注意的是,PLT的补充是GOT全球抵消表。当PLT用于函数调用时,GOT用于数据。