C语言编译 随笔

 这种在程序运行之前确定符号地址的过程叫做静态链接(Static Linking);如果需要等到程序运行期间再确定符号地址,就叫做动态链接(Dynamic Linking)。
 Linux 下的 .so 必须要嵌入到可执行程序、作为可执行程序的一部分运行,它们所包含的符号的地址就是在程序运行期间确定的,所以称为动态链接库(Dynamic Linking Library)。


强符号和弱符号

C语言中的强符号与弱符号
C语言强、弱符号,强、弱引用

点击查看代码
void __attribute__((weak)) f()
{
        printf("original f..\n");
}

编译时链接所做的工作

链接过程将多个目标文以及所需的库文件(.so等)链接成最终的可执行文件(executable file)。
命令大致如下:
$ ld -o test.out test.o inc/mymath.o ...libraries...
上面可以看到最终连接依赖了两个文件,mymath.o test.0还有其他一些依赖库

链接的详细过程如下:

合并段

在elf文件中字节对齐是以4字节对齐的,在可执行程序中是以页的方式对齐的(一个页的大小为4k),因此如果我们在链接时将各个.o文件各个段单独的加载到可执行文件中,将会非常浪费空间:
image
因此我们需要合并段,调整段偏移,把每个.o文件的.text段合并在一起.data段合并在一起,这样在生成的可执行文件中,各个段都只有一个,如下图,由于在链接时只需要加载代码段(.text段)和数据段(.data段和.bss段)。因此合并段之后,在系统给我们分配内存时,只需要分配两个页面大小就可以,分别存放代码和数据

调整段偏移

image

汇总所有符号

每个obj文件在编译时都会生成自己的符号表,我们要把这些符号都合并起来进行符号解析

完成符号的重定位

在进行合并段,调整段偏移时,输入文件的各个段在连接后的虚拟地址就已经确定了,这一步完成后,连接器开始计算各个符号的虚拟地址,因为各个符号在段内的相对位置是固定的,所以段内各个符号的地址也已经是确定的了,只不过连接器需要给每个符号加上一个偏移量,使他们能够调整到正确的虚拟地址,这就是符号的重定位过程

在 elf文件中,有一个叫重定位表的结构专门用来保存这些与从定位有关的信息,重定位表在elf文件中往往是一个或多个段

C/C++语言编译链接过程

posted @ 2021-10-28 09:43  上官鸿信の  阅读(43)  评论(0编辑  收藏  举报