天星
读完需要
4分钟
速读仅需2分钟
1个
静态链接和静态库
静态链接是由链接器在链接时,将库的内容加入到示例程序中的过程。其中使用的库就是我们通常所说的静态库。
静态库可以简单的看成成一组目标文件的集合,即多个目标文件经过压缩打包形成的一个文件。(通过ar工具)
2
静态链接过程
现在的链接器空间分配策略基本上采用一种叫两步链接的方法。然后整个链接过程分为两步:
第一步:空间与地址分配。
扫描所有的输入目标文件,获得他们的各个段的长度,属性和位置,并且将输入目标文件中的符号表中所有的符号定义和符号引用收集起来,统一放到一个位数符号表。
这一步中,链接器将能够获得所有输入目标文件的段长,变为他们合并,计算出输出文件中各个段合并后的长度和位置,并建立映射关系。
第二步:符号解析与重定位。
使用初步中收集到的所有信息,读取输入文件中段的数据,重定位信息,并进行符号解析和重定位,调整代码中的地址等。
3
静态库的制作和使用
查看静态库包含的目标文件
-t表示列出包含的所有目标文件
ar-tlibc.a
截取部分。可以看到glibc库包含了很多目标文件。
解压目标文件
-x表示解压库文件,交替解压所有
ar-xlibc.a//解压指定文件ar-xlibc.aprintf.o//从libc.a中解压指定printf.o
制作目标文件
-r:替换替换文件中已有的文件或加入新文件;-c:没有创建库的时候发出警告;-s:创建索引
ar-rcslibab.aa.ob.oar-rcs*.olibc.a
静态库使用
-L:指定链接链接;-l后面跟随链接的库名(去掉lib)
gcc-Llinkpath-lnamegcc-L./-lab(libab.a恰头去尾)
4
实例分析:最小的程序
知道了静态链接过程,以及程序大部分运行时都离不开libc,那么可不可以绕开glibc,写一个最小程序呢?
另外程序可以没有main函数吗?
答案是可以,这里涉及到操作系统的系统调用和底层知识,如果对操作系统和汇编体系比较熟悉,当然可以绕开。系统调用留待后续介绍。
如图,为一个最小的程序,并且没有main函数入口:
手动链接
编译:gcc-c-fno-builtinnomain.c-m32
-fno-builtin:关闭GCC内置函数功能-m32:指定32为系统。默认是64位的,不加会报错。
链接:ld-melf_i-static-enomain-ohelloworldnomain.o
-m:设置文件输出格式为elf_i。-static:表示静态链接.-enomain:设置程序入口函数为nomain
使用链接脚本
事实上,链接器在链接时默认有个链接脚本。函数的入口地址,以及各段分部,都可以通过链接脚本控制。我们程序当然也可以指定链接脚本。链接脚本的语法规则本文暂不介绍。
链接:ld-melf_i-static-Tnomain.lds-ohelloworldnomain.o
通过该脚本指定入口符号为nomain、将代码段、数据段和只读数据段合并为tinytext,同时舍弃.