fel*_*eek 3 linux x86 assembly elf dynamic-linking
考虑这段代码:
int foo();
int main() {
foo();
while(1){}
}
Run Code Online (Sandbox Code Playgroud)
int foo()在共享对象中实现。
编译此代码会gcc -o main main.c -lfoo -nostdlib -m32 -O2 -e main --no-pic -L./shared给出以下diasm:
$ objdump -d ./main
./main: file format elf32-i386
Disassembly of section .plt:
00000240 <.plt>:
240: ff b3 04 00 00 00 pushl 0x4(%ebx)
246: ff a3 08 00 00 00 jmp *0x8(%ebx)
24c: 00 00 add %al,(%eax)
...
00000250 <foo@plt>:
250: ff a3 0c 00 00 00 jmp *0xc(%ebx)
256: 68 00 00 00 00 push $0x0
25b: e9 e0 ff ff ff jmp 240 <.plt>
Disassembly of section .text:
00000260 <main>:
260: 8d 4c 24 04 lea 0x4(%esp),%ecx
264: 83 e4 f0 and $0xfffffff0,%esp
267: ff 71 fc pushl -0x4(%ecx)
26a: 55 push %ebp
26b: 89 e5 mov %esp,%ebp
26d: 51 push %ecx
26e: 83 ec 04 sub $0x4,%esp
271: e8 fc ff ff ff call 272 <main+0x12>
276: eb fe jmp 276 <main+0x16>
Run Code Online (Sandbox Code Playgroud)
通过以下搬迁:
$ objdump -R ./main
./main: file format elf32-i386
DYNAMIC RELOCATION RECORDS
OFFSET TYPE VALUE
00000272 R_386_PC32 foo
00001ffc R_386_JUMP_SLOT foo
Run Code Online (Sandbox Code Playgroud)
注意:
--no-pic,所以它不是 PICfoo()中对 的调用不经过 PLT。相反,这只是一个简单的重定位,我假设它将直接重定位到.textmainR_386_PC32foo重定位,我假设它将在加载时这对我来说很有意义,因为代码不是 PIC,因此无需通过 PLT 添加额外的间接寻址。foo,我们甚至进行了重定位,以便在加载时在 GOT 中R_386_JUMP_SLOT设置该条目(PLT 指向的条目)。foo我的问题很简单:我没有看到代码中的任何地方使用了 PLT,而且我也没有看到它在这里有必要,那么为什么 gcc 创建它呢?
--no-pic不像-no-pie,它似乎是代码生成的同义词-fno-pic或-fno-pie影响代码生成,但不链接。假设您的发行版的 GCC 默认创建 PIE,那么您正在创建 PIE,因此不会将调用转换为foo@plt.
我收到链接器警告/tmp/ccyRsNtd.o: warning: relocation against 'getpid@@GLIBC_2.0' in read-only section '.text.startup'/ warning: creating DT_TEXTREL in a PIE。(但是可执行文件确实可以运行,这与 64 位不同,64 位call rel32不能重定位到整个地址空间。)
是的,由于某种原因,有一个未使用的 PLT 条目ld,但您的链接方式完全是非标准的。
构建 PLT 的正常原因是:
ld当链接非 PIE 时,将转换call foo为call foo@plt而不是在每个调用站点包含文本重定位,每次程序加载时都需要运行时修复。
用于-fno-plt获得更高效的 asm,特别是对于 64 位模式,甚至 PIE 代码也可以有效地直接引用 GOT。
为了举一个更简单的例子,我使用了 libc ( ) 中的函数getpid而不是自定义库。使用 正常编译gcc -fno-pie -no-pie -m32 -O2 foo.c,我得到 5 字节e8 d5 ff ff ff调用 rel32: call 8049040 <getpid@plt>。
但除此之外-fno-plt,我得到了 6 字节ff 15 f4 bf 04 08 call [disp32]- call DWORD PTR ds:0x804bff4。不涉及 PLT,仅涉及绝对地址引用的 GOT 条目。
无需运行时重定位;该.text部分的此页面可以作为可执行文件的文件支持的私有映射保持“干净”。(运行时重定位会弄脏它,如果内核想要逐出该页面,则它只能由交换空间支持。)
此外,它使用需要早期绑定的“正常”GOT 条目。-nostdlib -lc即使对于不明智的人来说,这也确实有效,-e main而不是_start像正常人那样称呼它。由于它是动态链接的可执行文件,因此动态链接器确实在入口点之前运行并设置 GOT。
| 归档时间: |
|
| 查看次数: |
2307 次 |
| 最近记录: |