符号及符号解析
符号和符号表
符号的本质:ELF文件中存储的一块空间的首地址
定义的符号(函数,非局部变量)记录在符号表
将对符号的引用存在重定位节
分类:- 全局符号:不带static,本模块定义
- 外部符号:其他模块定义的,在本模块extern 声明
- 局部符号:带static
符号表:
描述该符号所在的位置(处于哪个节(索引),偏移多少,大小多少,符号类型等)
链接规则
全局符号的类型(只有全局才能是强符号)- 强符号:函数和已经初始化的变量名
- 弱符号:未初始化的变量名
解析规则(是否链接错误): - 强符号只能有一次定义
- 一次强符号,多次弱符号:按强定义处理
- 多个弱符号定义:任选其中一个
静态链接:
静态链接对象:多个.o + 静态库(.a包括多个.o)
良好的编码风格:- 避免所有函数写在一个.c中:每次修改要重新编译
- 避免一个.c只写一个函数:增加了链接的负担
静态共享库:多个.o打包成.a
gcc -c my1.c my2.c
ar rcs mylib.a my1.o my2.o
gcc -c main.c
gcc -static -o mypro main.o ./mylib.a
- 静态解析过程
//myfun1.c
#include <stdio.h>
void myfun1(){
printf("fun1");
}
//myfun2.c
#include <stdio.h>
void myfun2(){
printf("fun2")
}
//main.c
void myfun1();
int main()}{
myfun1();
return 0;
}
gcc -c myfun1.c myfun2.c
ar rcs mylib.a myfun1.o myfun2.o
gcc -c main.c
gcc -static -o mypro main.o ./mylib.a
调用过程:
main()-->myfun1-->printf
解析过程:按命令的顺序解析(静态库写在命令行最后)
1.E:带合并的.o文件
2.U:为解析的符号
3.D: 有定义的符号
- 链接的步骤:
- 符号解析得到集合E,集合D
- 合并E中所有.o
- 重定位D中所有符号