【发布时间】:2023-03-09 13:52:01
【问题描述】:
我有一个关于共享库的处理和解释的问题。
假设,我使用以下命令从 foo.c 构建一个共享对象:
gcc -shared -fPIC -o libfoo.so foo.c
其中 foo.c 包含:
#include <stdlib.h>
#include <stdio.h>
int main(void) {
int i;
printf("this is a silly test\n");
if(i)
goto ret;
printf("hello world\n");
ret:
return 0;
}
现在,让我们看看 objdump 的输出,特别是 foo 的 main 输出:
0000000005ec <main>:
5ec: 55 push %rbp
5ed: 48 89 e5 mov %rsp,%rbp
5f0: 48 83 ec 10 sub $0x10,%rsp
5f4: 48 8d 3d 6b 00 00 00 lea 0x6b(%rip),%rdi # 666 <_fini+0xe>
5fb: e8 00 ff ff ff callq 500 <puts@plt>
600: 83 7d fc 00 cmpl $0x0,-0x4(%rbp)
604: 75 0e jne 614 <main+0x28>
606: 48 8d 3d 65 00 00 00 lea 0x65(%rip),%rdi # 672 <_fini+0x1a>
60d: e8 ee fe ff ff callq 500 <puts@plt>
612: eb 01 jmp 615 <main+0x29>
614: 90 nop
615: b8 00 00 00 00 mov $0x0,%eax
61a: c9 leaveq
61b: c3 retq
61c: 90 nop
61d: 90 nop
61e: 90 nop
61f: 90 nop
我可以清楚地看到,对 put 的调用正按预期重定向到 PLT。但是,我不明白的是604和612的指令。它们与IP无关,也不是对PLT的调用。他们使用绝对地址,基于 符号主要。
这个共享库怎么可能在多个进程之间同时使用呢?它可以(并且应该)加载到不同的虚拟地址,但关键是每个进程应该共享存储在 RAM 中的实现。 main 加载在不同虚拟地址的不同进程如何共享 604 和 612 处的指令?
【问题讨论】:
-
X86 操作码
75(十六进制)和eb是相对跳转,而不是绝对跳转,您的清单中的操作数说明了这一点。反汇编可能会因为给出实际的目标地址而使您感到困惑;而是查看机器代码。
标签: c unix linker dynamic-linking