gcc 动态编译 与静态编译

对静态编译的程序而言,

.o文件中的符号表

一是要对外宣称自己定义了哪些符号,

二是向外宣布自己引用了哪些符号,需要其他模块来支持。

有了这些信息,static linker才能整合各个relocatable object file中的资源,互通有无,最后融合成一个静态的可执行程序。


因此,实际上,对于静态的可执行程序,在加载执行的时候,其符号表已经没有任何意义了(可以方便debug),
对于CPU而言,其执行就是要知道地址就OK了(静态编译程序所有的符号都已经定位了),符号什么的它不关心,因此,实际上符号表可以删除。
如果你愿意,你可以通过strip命令来进行实验,看看tripped和not stripped的elf文件有什么不同。



动态链接的符号表



通过readelf工具,我们可以看到,动态链接的程序中有两个符号表,
一个是大家之前就熟悉的.symtab section(我们称之符号表),
另外一个就是.dynsym section(动态符号表)。

这两个符号表都有自己对应的string table,分别是.strtab和.dynstr section。
.symtab section我们前面的文章都有描述,


为何又增加了一个.dynsym section呢?
我们先假设我们编译出来的动态库只有一个符号表,那么当使用strip命令删除符号表以及对应的字符串表之后会怎样?
当其他程序调用该动态库提供的接口API函数的时候,dynamic linker还能找到对应的API函数符号吗?当然不行,符号表都删除了还想怎样。

静态链接的程序之所以可以strip掉符号表以及对应的字符串表那是因为程序中所有符号都已经尘埃落定(所有符号已经重定位),因此strip后也毫无压力,

但是动态链接的情况下,程序中的没有定位的符号以及动态库中宣称的符号都需要有一个特别的符号表(是正常符号表的子集)来保存动态链接符号的信息,这个表就是动态连接符号表(.dynsym section)。

OK,最后总结一下:
符号表(.symtab section)是指导static linker工作的,运行的时候可以不需要。
动态符号表(.dynsym section)是给dynamic linker用的,程序(或者动态库)运行的时候,dynamic linker用动态符号表的信息来定位符号。


binding属性(binding property)的解释。一个符号可能有global、local和weak三种binding property。
这如何找到动态链接的信息 和静态链接的可执行序程序相比,DYNAMIC那个program header entry是动态库文件特有的。 既然是动态库,当然要参与动态链接的过程,因此动态库的ELF文件需要提供一些dynamic linking信息给OS以及dynamic linker,DYNAMIC那个program header entry就是起这个作用的。dynamic segment只包含了一个section,名字是.dynamic。需要注意的是.dynamic section也是data segment的一部分被加载到了进程的地址空间中。下面我们仔细看看libfoo.so的Dynamic section的内容:  ABS表示不该被重定位;UND表示未定义;COM表示未初始化数据(.bss),此时,value表示对齐要求,size给出最小大小