空间分配
例子:
/*a.c*/
extern int shared;
int main()
{
int a = 100;
swap(&a,&shared);
return 0;
}
/*b.c*/
int shared = 1;
void swap(int *a,int *b)
{
int temp;
temp = (*a);
(*a) = (*b);
(*b) = temp;
}
/*编译步骤*/
gcc -c a.c b.c
下面进行空间分配:
A 按序叠加
B 相似段合并
两步链接法
1 扫描输入文件,得到段属性,收集符号定义和引用,放到全局符号表,链接器得到每一个目标文件的段长,计算输出文件的合并段长和位置,建立映射关系。
2 读取文件中段数据和重定位信息,进行符号解析,重定位,和调整代码中地址。
重定位和符号解析
在其他目标文件中定义的变量或者函数(通称符号),编译器会把他们的地址暂时以0x00000000和0xFFFFFFFC代替,真正的计算过程则交给了链接器。链接器完成空间和地址的分配之后可以确定所有符号的虚拟地址,根据虚拟地址,对每一个需要重定位的指令修改。
需要重定位的指令: 这里会有一个重定位表,或称重定位段,加入代码段有序哟重定位的指令,则会有相应的.rel.data段。
重定位表的结构:
typedef struct {
Elf32_Addr r_offset;//修正位置第一个字节相对于段的偏移
Elf32_Word r_info;//重定位入口符号和类型
}Elf32_Rel;
静态库简述
出现原因:零散的目标文件提供给使用者,会有文件传输管理等不便,把这些目标文件压缩在一起,便于查找,形成libc.a静态库文件。
比如:
以下是通过解压printf.o得来的编译过程: