Android NDK 链接器无法找到两个共享库之间的符号

问题描述 投票:0回答:1

尝试使用我的本机库“contribtests.so”访问动态编译的 BZip2 库“libbz2.so”在调用 System.loadLibrary(“contribtests”) 时总是失败

java.lang.UnsatisfiedLinkError:dlopen失败:无法找到符号 引用的“BZ2_bzlibVersion” “/data/app/~~aTgFU-pNoDjbLJvJTuDiiQ==/com.microcaet.contribtests

我解压生成的 apk 并使用 readelf 检查站点。这两个库似乎都很好

[llothar@linux-workstation a]$ readelf -d lib/arm64-v8a/libbz2.so 

Dynamic section at offset 0xf478 contains 24 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libdl.so]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so]
 0x000000000000000e (SONAME)             Library soname: [libbz2.so]
 0x000000000000001e (FLAGS)              BIND_NOW
 0x000000006ffffffb (FLAGS_1)            Flags: NOW
 0x0000000000000007 (RELA)               0xd40
 0x0000000000000008 (RELASZ)             192 (bytes)
 0x0000000000000009 (RELAENT)            24 (bytes)
 0x000000006ffffff9 (RELACOUNT)          3
 0x0000000000000017 (JMPREL)             0xe00
 0x0000000000000002 (PLTRELSZ)           840 (bytes)
 0x0000000000000003 (PLTGOT)             0x11620
 0x0000000000000014 (PLTREL)             RELA
 0x0000000000000006 (SYMTAB)             0x308
 0x000000000000000b (SYMENT)             24 (bytes)
 0x0000000000000005 (STRTAB)             0x20098
 0x000000000000000a (STRSZ)              800 (bytes)
 0x000000006ffffef5 (GNU_HASH)           0x928
 0x000000000000001a (FINI_ARRAY)         0x11468
 0x000000000000001c (FINI_ARRAYSZ)       16 (bytes)
 0x000000006ffffff0 (VERSYM)             0x890
 0x000000006ffffffe (VERNEED)            0x908
 0x000000006fffffff (VERNEEDNUM)         1
 0x0000000000000000 (NULL)               0x0

这是包含调用 bz2 的 JNI 调用的一个

[llothar@linux-workstation a]$ readelf -d lib/arm64-v8a/libcontribtests.so 

Dynamic section at offset 0x144d18 contains 41 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libzip.so]
 0x0000000000000001 (NEEDED)             Shared library: [libcurl.so]
 0x0000000000000001 (NEEDED)             Shared library: [libnghttp2.so]
 0x0000000000000001 (NEEDED)             Shared library: [libssl.so]
 0x0000000000000001 (NEEDED)             Shared library: [libcrypto.so]
 0x0000000000000001 (NEEDED)             Shared library: [libarchive.so]
 0x0000000000000001 (NEEDED)             Shared library: [libcares.so]
 0x0000000000000001 (NEEDED)             Shared library: [liblzma.so]
 0x0000000000000001 (NEEDED)             Shared library: [libssh.so]
 0x0000000000000001 (NEEDED)             Shared library: [libbz2.so]
 0x0000000000000001 (NEEDED)             Shared library: [libzstd.so]
 0x0000000000000001 (NEEDED)             Shared library: [libz.so]
 0x0000000000000001 (NEEDED)             Shared library: [libandroid.so]
 0x0000000000000001 (NEEDED)             Shared library: [liblog.so]
 0x0000000000000001 (NEEDED)             Shared library: [libm.so]
 0x0000000000000001 (NEEDED)             Shared library: [libdl.so]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so]
 0x000000000000000e (SONAME)             Library soname: [libcontribtests.so]
 0x000000000000001e (FLAGS)              BIND_NOW
 0x000000006ffffffb (FLAGS_1)            Flags: NOW
 0x0000000000000007 (RELA)               0x43268
 0x0000000000000008 (RELASZ)             78840 (bytes)
 0x0000000000000009 (RELAENT)            24 (bytes)
 0x000000006ffffff9 (RELACOUNT)          1287
 0x0000000000000017 (JMPREL)             0x56660
 0x0000000000000002 (PLTRELSZ)           27792 (bytes)
 0x0000000000000003 (PLTGOT)             0x147588
 0x0000000000000014 (PLTREL)             RELA
 0x0000000000000006 (SYMTAB)             0x330
 0x000000000000000b (SYMENT)             24 (bytes)
 0x0000000000000005 (STRTAB)             0x188d4
 0x000000000000000a (STRSZ)              174480 (bytes)
 0x000000006ffffef5 (GNU_HASH)           0x13188
 0x0000000000000019 (INIT_ARRAY)         0x146ce8
 0x000000000000001b (INIT_ARRAYSZ)       48 (bytes)
 0x000000000000001a (FINI_ARRAY)         0x146cd8
 0x000000000000001c (FINI_ARRAYSZ)       16 (bytes)
 0x000000006ffffff0 (VERSYM)             0x119e8
 0x000000006ffffffe (VERNEED)            0x13124
 0x000000006fffffff (VERNEEDNUM)         3
 0x0000000000000000 (NULL)               0x0

在错误消息中查找提到的函数名称时,我发现了 在 libbz2.so 中定义并在调用库中标记为 UND(未定义)的符号。

[llothar@linux-workstation a]$ readelf -s lib/arm64-v8a/libbz2.so | grep bzlibVer
    40: 000000000000d34c    12 FUNC    GLOBAL DEFAULT   10 BZ2_bzlibVersion

[llothar@linux-workstation a]$ readelf -s lib/arm64-v8a/libcontribtests.so | grep bzlibVer
     5: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND BZ2_bzlibVersion
[llothar@linux-workstation a]$ 

唯一的想法是它可能会发生,因为编译创建了一个具有语义版本号“libbz2.so.1.0.9”的库。我正在使用 patchelf 工具删除“.1.0.9”,执行“patchelf --set-soname new_name old_name”,然后重命名该文件,否则 gradle 不会将该版本打包到生成的 apk 中。

作为测试,我还生成了“contribtests”作为简单的“main.c”来调用该函数并将其作为命令行程序执行(通过adb上传)。这与我复制到 JniLib 位置的重命名的“libbz2.so”完全相同。但我在运行之前设置了 LD_LIBRARY_PATH。

我怎样才能找到发生了什么?我现在完全无助。 如何修复或调试这个问题?我假设 so 文件已经正确加载。因此,符号解决的黑暗深处的某些东西正在造成这个问题。

android c linker android-ndk
1个回答
0
投票

好的,我想我找到了问题。

虽然“patchelf --set-soname new_name old_name”正在删除 SO 名称中的编号,但链接器还将在 patchelf 更新的可执行文件中设置一些其他隐藏位置。

使其链接的唯一方法是修补构建脚本,而不是首先在 SO 文件中创建符号版本。

这很糟糕,因为没有办法在不打补丁的情况下配置通用构建脚本(除非我错过了一些东西)。使得现有代码的移植变得不那么容易。

© www.soinside.com 2019 - 2024. All rights reserved.