Java教程

程序员的自我修养2.1 静态链接-两步链接

本文主要是介绍程序员的自我修养2.1 静态链接-两步链接,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

静态链接

  • 本文需要用到的代码
#include<stdio.h>
int global_init_val = 84; //.data
int global_uninit_val;
__attribute__((section("FOO"))) int global = 42;//FOO
int main(){
        int init_a = 20;
        int uninit_b;
        static int static_b = 40;//.data
        static int static_uninit_c;
        return 0;
}

  • 对于链接器来说,整个链接过程,就是将几个输入目标文件加工合并成一个输出文件,由目标文件.o到可执行文件.out,合并方式一般由两种
    1. 按序叠加,其实就是把a.o的所有段放好了,然后接下来放b.o的所有段,但是这种方法有缺点
      1. 首先就是每个文件的段都是分开的,导致最后的可执行文件的段可能有许多个,非常的浪费空间
      2. 内存的基本分配单位是页,所以每个段都会至少占据一个页,那么就会产生非常多的页内碎片
    2. 相似段合并 : 把几个输入目标文件的一样的段放一起,比如把a.o和b.o的.text放一起,然后放.data,现在一般都是这种方式

两步链接

  1. 空间和地址分配
    1. 分配虚拟空间
    2. 更新符号地址
  2. 符号解析和重定位

空间和地址分配

  1. 分配虚拟空间

在这里插入图片描述

  1. 将所有目标文件的符号表以及相关信息整合成一个全局符号表,通过给每个符号加上一个偏移量就可以得出符号的虚拟地址,比如main函数原本相对.text的偏移是X(这个y通过查看该目标文件的符号表就可以知道readelf -s hello2.o),而分配虚拟空间后,.text的虚拟空间是Y,所以main的最终的虚拟地址就是X+Y
  • 注意 : linux中,虚拟空间默认从0x08048000开始分配

符号解析和重定位

  • 在ELF文件格式中,存在一个重定位表,该表记录的信息是:该目标文件所有存在外部引用的地方,而重定位表往往由多个,比如.ref.text,.ref.rodata,使用objdump -r hello2.o可以查看文件的重定位表
    在这里插入图片描述

  • 符号解析就是根据重定位表,找到哪里需要重定位,重定位的符号是什么,然后再去全局符号表找到该符号的虚拟地址

  • 指令修正方式,<<程序员的自我修养>>这本书p109有详细的例子说明

这篇关于程序员的自我修养2.1 静态链接-两步链接的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!