0%

C语言-链接与编译

编译

源文件生成目标文件的过程及main.c–main.o

链接

目标文件生成可执行文件的过程及main.o–main。详细点说链接是将编译之后的所有目标文件连同用到的一些静态库、运行时库组件而拼装成一个可执行文件的过程。其中有地址修复的过程,如上图所示call后面的地址暂时被设置为0,修复时就是链接器根据目标文件或者静态库中的重定位表找到那些需要被重定位的函数和全局变量从而修正他们的地址。

对于add.h 、add.c、main.c三个文件

add.h

1
int add(int a,int b);

add.c

1
2
3
4
int add(int a,int b)
{
return a+b;
}

main.c

1
2
3
4
5
6
7
8
9
#include<stdio.h>
#include"add.h"
int main()
{
int a=5;
int b=10;
printf("a+b=%d\n",addd(a,b));
return 0;
}

编译器是完全不知道printf和add函数的存在的(位于哪个区块、函数的定义),因此编译器只能将两个函数的跳转先暂时设置为0.使用odjdump对目标文件进行反汇编

1
objdump -s -d main.o > main.o.txt

这里的0会在后面链接的时候被修正

查看目标文件的重定位信息

1
objdump -r main.o

函数add、printf的偏移量分别为25、3b。

一直手工编译显然效率不高,学习了一点makefile的知识

1
vim makefile
1
2
3
4
5
6
7
8
9
all:main
main:main.o add.o
gcc main.o add.o -o main
main.o:main.c
gcc -c main.c
add.o:add.c
gcc -c add.c
clean:
rm main main.o add.o

然后make main即可,他会自动根据依赖树递归地去构建可执行文件main

参考:https://www.youtube.com/watch?v=1IIUvVrCSF0