最近在移植代码的时候,出现一个问题,加载动态库失败。之前是没有问题的,查了很多资料,发现是因为这个动态库所信赖的另外一个动态库发生了变化导致的。
通过这次的解bug过程,我对动态库的生成与加载有了更深一层次的了解,在此做下总结。
1、因为要跟踪加载过程,所以要在bionic打印log,所以还要设置一下,代码更改如下:
//1.linker_debug.h中的#define LINKER_DEBUG和#define TRACE_DEBUG都改为1。当然也可以在Android.mk里添加
//2.linker.c中的
#define HOODLUM(name, ret, ...) \
ret name __VA_ARGS__ \
{ \
char errstr[] = "ERROR: " #name " called from the dynamic linker!\n"; \
write(2, errstr, sizeof(errstr)); \
abort(); \
}
HOODLUM(malloc, void *, (size_t size));
HOODLUM(free, void, (void *ptr));
HOODLUM(realloc, void *, (void *ptr, size_t size));
HOODLUM(calloc, void *, (size_t cnt, size_t size));
//这一段注释掉。
//3.Android.mk中的
LOCAL_STATIC_LIBRARIES := libcutils libc_nomalloc
//改成
LOCAL_STATIC_LIBRARIES := libcutils \
libc
//4.重新编译linker,上传到模拟器或实际设备,export DEBUG=3,然后执行命令就看到linker输出的log了。
详见:如何让android的bionic中的linker输出调试信息
2、加载某个库失败了,不一定是这个库导致的,也可能是这个库所信赖的库加载失败了。在加载一个库的时候,会先加载其所依赖的库,这些信息都写在.so文件里。
所依赖的库,在Android.mk里有体现:
LOCAL_SHARED_LIBRARIES += liblog
LOCAL_PRELINK_MODULE := false
LOCAL_MODULE := libcamera
这就说明了,在编译时会把liblog.so写进生成的.so文件的依赖库列表里。当然,你加上<cutils/log.h>头文件,就可以在代码里调用liblog.so里的函数了。
可在 Android.mk 中设置该库是否需要 Prelink ,默认是使用 Prelink 的,也可设置成否,方法如下:
LOCAL_PRELINK_MODULE := false