我如何知道 Android .so 是用哪个运行时编译的?
How can I tell which runtime an Android .so was compiled with?
我有一些预编译的 so 文件,所以谁知道生成它们时使用了哪些标志。我很想知道它们是用哪个 runtime/version STL 编译的(gnustl_shared?stlport_shared?)以避免与我自己的代码发生冲突。
如何从编译后的 so 文件中找出它们被编译使用的运行时?
这是所有 Android NDK C++ 代码。
NDK 附带一个名为 readelf 的实用程序(在 NDK/toolchains 下)。要查看预构建二进制文件需要哪个共享 STL 库,您可以 运行
$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/*/bin/arm-linux-androideabi-readelf -a 3rd-party-lib.so | grep NEEDED | grep _shared
版本有问题。 STL 共享二进制文件没有版本信息,我不相信存在测试它们向后兼容性的过程。尽管如此,stlport abd gnustl 至少已经稳定了两年。
你通常可以determine what compiler was used to build the binary,但不,NDK 编译器并不总是随着每个 NDK 版本而改变。
正如 Alex 所说,您可以使用 readelf 来解决其中的一些问题。以下内容可以让您知道该库是否依赖于共享的 STL,以及是哪一个:
$ readelf -dW path/to/libfoo.so | grep NEEDED
0x00000001 (NEEDED) Shared library: [libc++_shared.so]
0x00000001 (NEEDED) Shared library: [libc.so]
0x00000001 (NEEDED) Shared library: [libm.so]
0x00000001 (NEEDED) Shared library: [libstdc++.so]
0x00000001 (NEEDED) Shared library: [libdl.so]
如你所见,这个库依赖于libc++_shared。忽略 libstdc++。这样你也能看到。那是 https://github.com/android-ndk/ndk/issues/105.
如果它依赖于静态 STL(或者您的库是静态库)并且 不是 使用 -fvisibility=hidden
构建的,则该方法将不起作用。在这种情况下,您仍然可以确定该库是针对 libc++ 还是非 libc++ 构建的。所有 libc++ 符号都在内部命名空间中(std::__ndk1
而不仅仅是 std
)以支持对 STL 进行版本控制并避免与系统 STL 发生冲突。如果它是一个非常旧的(r10 或更旧的)libc++,它将只是 __1
.
$ readelf -sW path/to/libfoo.so | grep __ndk1
6: 000008bf 86 FUNC WEAK DEFAULT 12 _ZNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6__initEPKcj
7: 000008a9 22 FUNC WEAK DEFAULT 12 _ZNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEED2Ev
如果您想了解库是用哪个版本的 NDK 构建的,可以使用 https://android.googlesource.com/platform/ndk/+/master/parse_elfnote.py。
$ python parse_elfnote.py foo/libs/armeabi-v7a/libfoo.so
----------ABI INFO----------
ABI_NOTETYPE: 1
ABI_VENDOR: Android
ABI_ANDROID_API: 14
ABI_NDK_VERSION: r17-canary
ABI_NDK_BUILD_NUMBER: dev
大部分信息仅适用于使用相对较新的 NDK 构建的库(r14?我不记得我们何时添加了它)。
我有一些预编译的 so 文件,所以谁知道生成它们时使用了哪些标志。我很想知道它们是用哪个 runtime/version STL 编译的(gnustl_shared?stlport_shared?)以避免与我自己的代码发生冲突。
如何从编译后的 so 文件中找出它们被编译使用的运行时?
这是所有 Android NDK C++ 代码。
NDK 附带一个名为 readelf 的实用程序(在 NDK/toolchains 下)。要查看预构建二进制文件需要哪个共享 STL 库,您可以 运行
$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/*/bin/arm-linux-androideabi-readelf -a 3rd-party-lib.so | grep NEEDED | grep _shared
版本有问题。 STL 共享二进制文件没有版本信息,我不相信存在测试它们向后兼容性的过程。尽管如此,stlport abd gnustl 至少已经稳定了两年。
你通常可以determine what compiler was used to build the binary,但不,NDK 编译器并不总是随着每个 NDK 版本而改变。
正如 Alex 所说,您可以使用 readelf 来解决其中的一些问题。以下内容可以让您知道该库是否依赖于共享的 STL,以及是哪一个:
$ readelf -dW path/to/libfoo.so | grep NEEDED
0x00000001 (NEEDED) Shared library: [libc++_shared.so]
0x00000001 (NEEDED) Shared library: [libc.so]
0x00000001 (NEEDED) Shared library: [libm.so]
0x00000001 (NEEDED) Shared library: [libstdc++.so]
0x00000001 (NEEDED) Shared library: [libdl.so]
如你所见,这个库依赖于libc++_shared。忽略 libstdc++。这样你也能看到。那是 https://github.com/android-ndk/ndk/issues/105.
如果它依赖于静态 STL(或者您的库是静态库)并且 不是 使用 -fvisibility=hidden
构建的,则该方法将不起作用。在这种情况下,您仍然可以确定该库是针对 libc++ 还是非 libc++ 构建的。所有 libc++ 符号都在内部命名空间中(std::__ndk1
而不仅仅是 std
)以支持对 STL 进行版本控制并避免与系统 STL 发生冲突。如果它是一个非常旧的(r10 或更旧的)libc++,它将只是 __1
.
$ readelf -sW path/to/libfoo.so | grep __ndk1
6: 000008bf 86 FUNC WEAK DEFAULT 12 _ZNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6__initEPKcj
7: 000008a9 22 FUNC WEAK DEFAULT 12 _ZNSt6__ndk112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEED2Ev
如果您想了解库是用哪个版本的 NDK 构建的,可以使用 https://android.googlesource.com/platform/ndk/+/master/parse_elfnote.py。
$ python parse_elfnote.py foo/libs/armeabi-v7a/libfoo.so
----------ABI INFO----------
ABI_NOTETYPE: 1
ABI_VENDOR: Android
ABI_ANDROID_API: 14
ABI_NDK_VERSION: r17-canary
ABI_NDK_BUILD_NUMBER: dev
大部分信息仅适用于使用相对较新的 NDK 构建的库(r14?我不记得我们何时添加了它)。