动态链接,大家明白了吗?
(根据我们的经验,大家上课没听懂)
本讲内容
-fno-pic
编译;-static
链接// a.c
int foo(int a, int b) {
return a + b;
}
// b.c
int x = 100, y = 200;
// main.c
extern int x, y;
int foo(int a, int b); // 可以试试 extern int foo;
int main() {
printf("%d + %d = %d\n", x, y, foo(x, y));
}
Binary utilities: 分析二进制文件的工具
使用 binutils
x
, y
(-D
)-4
?由操作系统加载 (下学期内容)
你可以认为是 “一步到位” 的
不能用 ld 链接吗?
(试一试)
gcc -Wl,--verbose
C 世界里还有很多大家不知道的东西
__attribute__((constructor))
__attribute__((destructor))
(atexit)RTFM; RTFSC!
-fno-pic
和 -static
这是默认的 gcc 编译/链接选项。
文件相比静态链接大幅瘦身
a.o
, b.o
没有变化main.o
里依然有 00 00 00 00
a.out
里库的代码都不见了使用位置无关代码 (PIC) 的原因
-no-pie
选项编译PIC 的实现
movl $1, 1234(%eip)
__i686.get_pc_thunk.bx
命令:ldd
ldd 竟然是一个脚本 (vim $(which ldd)
)
--list
选项达到类似效果终于揭开谜题
readelf -a a.out
/lib64/ld-linux-x86-64.so.2
神奇的 ld.so
/lib64/ld-linux-x86-64.so.2 ./a.out
./a.out
的行为完全一致./a.out
真正在操作系统里发生的事情)#!
) 实现机制完全相同main.o 在链接时,对 printf 的调用地址就确定了
但 libc 每次加载的位置都不一样啊 !
应用程序使用怎样的指令序列调用库函数?
基本款
call *table[PRINTF]
-fno-plt
选项可以开启此款豪华款 (默认选项,使用 PLT)
printf@plt:
jmp *table[PRINTF]
push $PRINTF
call resolve
因为百度搜不到啊!
中文社区几乎不存在这些知识的详细解释
你们才是未来的希望
(RTFM; STFW; RTFSC)