源文件到可执行文件的过程
#include<stdio.h>
int main(){
printf("hello,world!");
return 0;
}
gcc -S -o test.s test.c 编译生成汇编文件test.s
(只编译,不汇编,不链接)
内容
汇编文件变成目标文件
gcc -c -o test.o test.s (编译且汇编,但不链接)
.o文件已经是01码了,但cat方式查看会转换成ASCII码
目标文件变成可执行文件(动态链接)
gcc -o test test.o
要是静态链接 则:gcc -static -o test test.o
通过编译器把.c文件变成汇编代码,再通过汇编器把.s文件翻译成.o文件(gcc可充当编译器和汇编器)。最后链接形成可执行性文件。
最后一步为什么要链接?
int main(){
printf("hello,world!");
reutrn 0;
}
int main和return 0是可以被识别翻译成机器码的,但是printf函数不是可以被识别的关键字。printf被写好编译在libc里,我们直接调用libc库用就可以。如果直接运行.o文件不链接的话,是缺省printf函数的。只有链接才知道printf函数实现在了哪里。以上所说的是动态链接的情况,静态链接也是如此,不链接就找不到函数在哪。
动态链接是在装载这一步可见的,需要哪个函数就会进行调用,在链接这一步只是知道需要的函数所实现的位置在哪。
静态链接在链接这一步就已经把所有需要的函数全部装载到elf文件中了。
windows和LINUX下的可执行性文件
ELF
elf文件从磁盘装载到内存
磁盘上的节可分为两大部分,可读可写的节有.data,.bss,.got.plt。 可读可执行的节有.rodata,.text,.init。当elf从磁盘被装载到内存上时,会根据这两大部分变成data段和code段。