您的位置:首页 > 产品设计 > UI/UE

Android加载so出现dlopen failed: empty/missing DT_HASH in "libx.so" (built with --hash-style=gnu?)错误

2016-01-07 19:44 579 查看
在网上搜了一下,参考下面两个帖子:
http://stackoverflow.com/questions/28638809/android-ndk-unsatisfiedlinkerror-dlopen-failed-empty-missing-dt-hash http://blog.csdn.net/asmcvc/article/details/47659057
摘自第二个帖子的解决方法:

The library you are trying to load was most likely built with Wl,hash-style=gnu. This was not supported on Android until recently (afaik this isn't even in L). You need to build your libraries with -Wl,-hash-style=sysv.

How did you build cpplibrary.so? If you didn't do anything to manually switch to the gnu hash style, it could be a bug in the NDK.

One option is to add "LOCAL_LDFLAGS := -Wl,--hash-style=sysv" at screenrecord Android.mk though I am sure there is a less hacky method of doing so..

总结了一下是需要在Android.mk中添加链接选项:

LOCAL_LDFLAGS := Wl,-hash-style=sysv

libsysv-hash-table-library_ldflags := Wl,-hash-style=sysv

于是在修改前后查看了一下so节的变化:
readelf.exe -d libxxxx.so

Dynamic section at offset 0xed14 contains 27 entries:
Tag Type Name/Value
0x00000003 (PLTGOT) 0xfee0
0x00000002 (PLTRELSZ) 552 (bytes)
0x00000017 (JMPREL) 0x46fc
0x00000014 (PLTREL) REL
0x00000011 (REL) 0x39c4
0x00000012 (RELSZ) 3384 (bytes)
0x00000013 (RELENT) 8 (bytes)
0x6ffffffa (RELCOUNT) 420
0x00000006 (SYMTAB) 0x148
0x0000000b (SYMENT) 16 (bytes)
0x00000005 (STRTAB) 0x1918
0x0000000a (STRSZ) 5780 (bytes)
0x00000004 (HASH) 0x2fac
0x00000001 (NEEDED) Shared library: [liblog.so]
0x00000001 (NEEDED) Shared library: [libdl.so]
0x00000001 (NEEDED) Shared library: [libstdc++.so]
0x00000001 (NEEDED) Shared library: [libm.so]
0x00000001 (NEEDED) Shared library: [libc.so]
0x0000000e (SONAME) Library soname: [libbugrpt.so]
0x0000001a (FINI_ARRAY) 0xf590
0x0000001c (FINI_ARRAYSZ) 8 (bytes)
0x00000019 (INIT_ARRAY) 0xf598
0x0000001b (INIT_ARRAYSZ) 16 (bytes)
0x00000010 (SYMBOLIC) 0x0
0x0000001e (FLAGS) SYMBOLIC BIND_NOW
0x6ffffffb (FLAGS_1) Flags: NOW
0x00000000 (NULL) 0x0


readelf.exe -d libxxxx.so

Dynamic section at offset 0xed14 contains 27 entries:
Tag Type Name/Value
0x00000003 (PLTGOT) 0xfee0
0x00000002 (PLTRELSZ) 552 (bytes)
0x00000017 (JMPREL) 0x46fc
0x00000014 (PLTREL) REL
0x00000011 (REL) 0x39c4
0x00000012 (RELSZ) 3384 (bytes)
0x00000013 (RELENT) 8 (bytes)
0x6ffffffa (RELCOUNT) 420
0x00000006 (SYMTAB) 0x148
0x0000000b (SYMENT) 16 (bytes)
0x00000005 (STRTAB) 0x1918
0x0000000a (STRSZ) 5780 (bytes)
0x00000004 (HASH) 0x2fac
0x00000001 (NEEDED) Shared library: [liblog.so]
0x00000001 (NEEDED) Shared library: [libdl.so]
0x00000001 (NEEDED) Shared library: [libstdc++.so]
0x00000001 (NEEDED) Shared library: [libm.so]
0x00000001 (NEEDED) Shared library: [libc.so]
0x0000000e (SONAME) Library soname: [libbugrpt.so]
0x0000001a (FINI_ARRAY) 0xf590
0x0000001c (FINI_ARRAYSZ) 8 (bytes)
0x00000019 (INIT_ARRAY) 0xf598
0x0000001b (INIT_ARRAYSZ) 16 (bytes)
0x00000010 (SYMBOLIC) 0x0
0x0000001e (FLAGS) SYMBOLIC BIND_NOW
0x6ffffffb (FLAGS_1) Flags: NOW
0x00000000 (NULL) 0x0


上面用readelf来查看so的结构,两者是没有区别的,这个需要研究一下ELF的文件结构和其中各个段,在so的.dynamic段中需要通过一个tag来找到hash section,从而去索引编译的符号,这个tag在一般的Linux中是DT_GNU_HASH,而在Android中是DT_HASH,两者是不一样的。

上面提示的错误信息说DT_HASH找不到或者为空,并提示是不是编译的时候使用了--hash-style=gnu的编译选项,说明在用这个编译选项以后这个tag名字就是DT_GNU_HASH了,所以系统加载so的时候才会出错。

但是现在想不明白的是这个崩溃是偶现的,而且概率很低,按理说如果so格式有问题应该是必崩的才对,真正的原因还没搞明白。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: