为什么“EVP_get_cipherbyname”符号仅在某些 Android 设备上导出?

Mat*_*uhn 5 android dynamic-linking android-ndk

我有一个用 Qt 为 Android 构建的应用程序。该应用程序附带自定义构建的 openssl 版本。这适用于大多数设备,但是,在一些设备上,一旦 https 请求完成,它就会崩溃。

一个例子是 SAMSUNG-SM-G930AZ,API 级别 26 (Android 8.0)。

崩溃时它会产生以下跟踪。

backtrace:
    #00 pc 00000000000667c4  /system/lib64/libc.so (strcasecmp+8)
    #01 pc 000000000023ddd0  /system/lib64/libandroid_runtime.so (EVP_get_cipherbyname+24)
    #02 pc 000000000003a5f0  /data/app/ch.opengis.qfield_beta-ojJ20GzjLOx-tvpq9AD27A==/lib/arm64/libssl_1_1.so (offset 0x29000)
Run Code Online (Sandbox Code Playgroud)

libandroid_runtime.so从这个设备下载了文件,其中列出了提到的符号

readelf -Ws libandroid_runtime.so | grep EVP_get_cipherbyname
  3593: 000000000023dd78   336 FUNC    GLOBAL DEFAULT   12 EVP_get_cipherbyname
Run Code Online (Sandbox Code Playgroud)

在另一个(不崩溃 SM-T580,Android 8.1)上,情况并非如此

readelf -Ws /tmp/libandroid_runtime.so | grep EVP_get_cipherbyname
Run Code Online (Sandbox Code Playgroud)

该符号也libcrypto_1_1.so随应用程序一起提供。我认为这次碰撞是导致崩溃的原因。

Android 文档中,Android 7 完成了以下 NDK 更改:

为了减少此限制可能对当前发布的应用程序产生的影响,libandroid_runtime.so针对 API 级别的应用程序,可以在 Android 7.0(API 级别 24)上临时访问一组具有重要用途的库(例如,[...]) 23 或更低。

该应用程序以 API 级别 29 为目标,因此我认为此库不应对此应用程序可用。

如何避免这种崩溃?是否可以阻止加载libandroid_runtime.so或可以使用特定标志编译 openssl 还是需要完全不同的方法?