2程序编译与链接

发布时间 2024-01-11 23:06:57作者: 二氧化硅21

程序编译与链接原理

img

  • 预编译:处理#命令,但保留#pragma,删除注释。
  • 编译:词法分析、语法分析、语义分析和优化,生成汇编代码。
  • 汇编:将汇编代码翻译成机器码(AT&T,x86语法),打包为可重定位二进制目标文件,此文件不可执行。输出符号表。
  • 链接:合并.o文件段,合并符号表,解析并符号重定向。
//以下为main文件
extern int gdata;  //gdata *UND*代表需使用但未定义
int sum(int, int);  //sum *UND*

int data = 20;  //data .data
int main(){  //main .text
    int a = gdata;
    int b = data;
    
    int ret = sum(a, b);
    return 0;
}

//以下为sum文件
int gdata = 10;  //gdata .data
int sum(int a, int b){ //sum_int_int .text
    return a + b;
}

以上为.o文件中的部分符号注释
具体的.o文件的格式组成包括各种段

img
img

编译过程中不为符号分配地址,通过readelf可以观察到地址皆为0。虽然指令已经在编译阶段翻译好,但变量地址皆为0,需要在链接阶段补充,也因此.o文件无法执行。

链接

链接过程合并若干个.o文件的段合并:text段合并,data段合并...,以及符号表的合并。

  • 符号表合并:检查符号表,所有对符号的引用(*UND*),都要找到该符号定义的地方,当然符号定义只能有一个,不可重定义,不可没有。最终符号解析成功。

  • 符号解析成功后,在代码段中,为所有符号分配虚拟地址,并把这些地址写回指令中。这个过程叫做符号重定向。

可执行文件

链接产生可执行文件,可执行文件与二进制可重定向文件段格式几乎一致,但可执行文件中多了一个program headers段,这其中包含若干load项,比如.text,.data,这意味着这些load项要在代码执行时,加载如虚拟内存空间