链接(linking) 是将各种代码和数据片段收集并组合成为一个单一文件的过程,这个文件可以被加载(复制)到内存并执行。
目标文件纯粹是字节块的集合。 这些块中,有些包含程序代码,有些包含程序数据,其他的则包含引导链接器和加载器的数据结构。链接器将这些块连接起来,确定被连接块的运行时位置,并且修改代码和数据块中的各种位置。
GNU binutils包 可以帮助理解和处理目标文件,且可以运行在每个Linux平台。
每个可重定位模块都有一个符号表,包含该模块定义和引用的符号的信息。
函数和已初始化的全局变量称为强变量,未初始化的变量称为弱变量。Linux链接器使用下面规则处理多重定义的符号名:
符号解析之后进行重定位,这一步将合并输入模块,并为每个符号分配运行时地址。重定位分为两步:
静态库需要定期维护和更新,而且相关函数的代码会被复制到每个运行进程的文本段中。
共享库是一个目标模块,在运行或加载时,可以加载到任意的内存地址,并和一个在内存中的程序链接起来。这个过程叫做动态链接,共享库也称为共享目标(shared object)。Linux系统中通常用.so后缀标识共享库,微软通常使用DLL(动态链接库)。
一个库只有一个.so文件,所有引用该库的可执行目标文件共享这个.so文件中的代码和数据,而不是像静态库的内容那样被复制和嵌入到引用它们的可执行文件中。在内存中一个共享库的.text节的一个副本可以被不同的正在运行的进程共享。
构造共享库的一个例子,使用如下指令:
linux> gcc -shared -fpic -o libvector.so addvec.c multvec.c // 使用共享库进行链接 linux> gcc -o prog21 main2.c ./libvector.so
可以加载而无需重定位的代码称为位置无关代码(Position-Independent Code,PIC),用户对GCC使用-fpic选项指示GNU编译系统生成PIC代码。共享库的编译必须总是使用该选项。
a
--
123456789
更改id为3
--
test
更改id为2
--
commentor
伪造名称???
--
hhh
伪造名称???
--
yayay