静态库链接学习

静态库链接学习

最近做的andriod项目中遇到了一个奇怪的bug,怀疑到了init进程内存越界,所以想用efence进行检查。

但是有个问题,以前用efence,都是用的动态库,而init中只能使用静态库。
原因么,就是init的Android.mk中有下面这个东东:
LOCAL_FORCE_STATIC_EXECUTABLE := true
静态库就静态库呗,反正原来已经使用了静态库:
LOCAL_STATIC_LIBRARIES :=  libcutils libc
直接把libefence加上:
LOCAL_STATIC_LIBRARIES :=  libcutils libc libefence
编译,提示malloc、free等几个函数重复定义,看了下代码,果然,efence中进行了定义,libc中也进行了定义。
动态库的时候没问题,是因为动态库的时候,函数名字不是mallog,而是efence_malloc,如果用了efence的话,在libc.so中会将malloc重新定向到efence_malloc。
但静态库就没有这样的处理。
在一位大牛的指导下,找到了解决办法。
修改efence中malloc等函数的名字,例如改为malloc_ef。
然后整个头文件,其中判断某个宏AAAA如果定义,就将malloc重新定向到malloc_ef。
init中每个.c文件都包含该头文件。
如果想用efence,就在Andoid.mk中的LOCAL_CFLAGS中加上-DAAAA。
OK,问题解决,重复定义没了。

不过又来了其他问题。
说sem_wait等几个semaphore相关的函数,还有strlcat和system函数找不到定义。
看了下代码,其中有定义。
libc的这部分代码中也没有对静态库和动态库作区别,动态库OK,静态库为什么不OK?
后来怀疑到是不是连接的时候没有去链bionic libc,而是去链gcc中默认的libc。默认的libc中可能没有定义这些东东。
虽然这样怀疑,但是不知道从何下手。

继续请教大牛。
这次找了另外一位编译大牛。
先找到libc.a,通过命令:readelf -sw libc.a | grep sem_wait,确认libc.a中有sem_wait的定义。
接下来怀疑是静态库链接的顺序问题。静态库链接还有顺序???
果然是顺序问题,修改为如下顺序:
LOCAL_STATIC_LIBRARIES := libefence libcutils libc
编译OK。
原来是,如果链接的多个静态库中有依赖关系,依赖者应该放在被依赖者前面。
从下面这句话中本应该也看出来点端倪:
LOCAL_STATIC_LIBRARIES :=  libcutils libc
libcutils肯定依赖于libc。不过当时没考虑到有顺序问题。

这样就大功告成了么?
另外一位大牛提示,其实有一个连接选项也可以解决这个问题:
LOCAL_LDFLAGS := -Wl,--whole-archive out/debug/target/product/imx51_bbg/obj/STATIC_LIBRARIES/libefence_intermediates/libefence.a -Wl,--no-whole-archive
该选项是用来解决两个.a文件互相依赖,这样顺序就不能解决它们的问题了。
注意,其中.a一定要给出全路径,不然会找不到.a。
加上了上面这个链接选项,按照如下的静态库顺序,仍然OK:
LOCAL_STATIC_LIBRARIES :=  libcutils libc libefence

在这个过程中,还学了几招:
choosecombo 模块名:可以为单个模块选择编译选项
make clean-模块名:可以clean单个模块。
make 模块名 showcommands:显示编译链接过程中的详细log。

不过还是有个疑问,我在测试上面这个链接选项LOCAL_LDFLAGS的时候,把libc.a放在选项的中间,提示说有些函数重复定义。
将libefence.a放在中间,OK。
同时将libc.a和libefence.a放在中间,还是提示函数重复定义。
再试一下下面这个顺序(同时加上上面的LOCAL_LDFLAGS选项):
LOCAL_STATIC_LIBRARIES :=  libc libcutils libefence
提示libcutils中部分定义找不到。
修改LOCAL_LDFLAGS:
LOCAL_LDFLAGS := -Wl,--whole-archive out/debug/target/product/imx51_bbg/obj/STATIC_LIBRARIES/libcutils_intermediates/libcutils.a out/debug/target/product/imx51_bbg/obj/STATIC_LIBRARIES/libefence_intermediates/libefence.a -Wl,--no-whole-archive
提示一些东东重复定义。
修改下顺序:
LOCAL_LDFLAGS := -Wl,--whole-archive out/debug/target/product/imx51_bbg/obj/STATIC_LIBRARIES/libefence_intermediates/libefence.a out/debug/target/product/imx51_bbg/obj/STATIC_LIBRARIES/libcutils_intermediates/libcutils.a -Wl,--no-whole-archive
效果一样。

有必要看看-Wl,--whole-archive了。
先看看gun linker手册中的介绍:
--whole-archive
For each archive mentioned on the command line after the --whole-archive option, include every object file in the archive in the link, rather than searching the archive for the required object files. This is normally used to turn an archive filele into a shared library, forcing every object to be included in the resulting shared library. This option may be used more than once.

can be used more than once?
那么上面LOCAL_LDFLAGS中包含libefence.a和libcutils时的链接错误是不是可以解决了
LOCAL_LDFLAGS := -Wl,--whole-archive out/debug/target/product/imx51_bbg/obj/STATIC_LIBRARIES/libefence_intermediates/libefence.a  -Wl,--no-whole-archive -Wl,--whole-archive  out/debug/target/product/imx51_bbg/obj/STATIC_LIBRARIES/libcutils_intermediates/libcutils.a -Wl,--no-whole-archive
还是解决不了。

重复定义的error似乎可以解释:
include every object file in the archive in the link, rather than searching the archive for the required object files
应该是包含了多余的object文件。也有可能是某些object file被重复包含了。

但是LOCAL_LDFLAGS中为什么必须是libefence.a,而不是libc.a?
按照我的理解,既然是libefence中有些定义找不到,而这些定义在libc中,应该将libc的all object files包含过来,而不是libefence的。

网上搜到了下面这篇文章:
http://blog.chinaunix.net/uid-22720671-id-3142655.html
其中有如下内容:
总结:
1)当使用--whole-archive时,其会把所有的--whole-archive之后的.sa中的所有函数全部加入到生成的文件中来,这样的情况下,如果有同名函数,则链接就不会通过;
2)当使用--no-whole-archieve时,则此后的所有文件中的所有函数都不会加到生成的文件中,但下面的第3点情况例外;
3)如果命令行中有.o文件,如test.o, 并且.o文件后面有.sa文件,则会把.o文件中用到的函数的.sa文件加入到生成的结果文件中来(即使.sa前有--no-whole-archieve);所以这和.o及.sa的顺序有关系。

但是还是解决不了我的疑问。

又搜索了些资料,还是没解决。
今天先学习到这吧。

庆幸身边有那么多大牛。
感谢帮助过我的大牛们!

 

你可能感兴趣的:(静态库链接学习)