libavcodec.so: 有文本重定位

libavcodec.so: has text relocations

我正在 Nexus 5 上测试 Android 6.0 并且我正在使用 Metaio(我知道该服务将在 12 月 15 日结束,但到那个日期我们将转移到另一个增强现实平台)。 问题是当我启动 ARActivity 时出现以下错误:

    09-02 08:45:11.138: E/AndroidRuntime(6141):     java.lang.UnsatisfiedLinkError: dlopen failed: /data/app/com.myapp.myapp/lib/arm/libavcodec.so: has text relocations
    09-02 08:45:11.138: E/AndroidRuntime(6141):     at java.lang.Runtime.loadLibrary(Runtime.java:372)
    09-02 08:45:11.138: E/AndroidRuntime(6141):     at java.lang.System.loadLibrary(System.java:1076)
    09-02 08:45:11.138: E/AndroidRuntime(6141):     at com.metaio.sdk.jni.IMetaioSDKAndroid.loadNativeLibs(IMetaioSDKAndroid.java:54)
    09-02 08:45:11.138: E/AndroidRuntime(6141):     at metaioCloudPlugin.SplashActivity.loadNativeLibs(SplashActivity.java:37)
    09-02 08:45:11.138: E/AndroidRuntime(6141):     at metaioCloudPlugin.SplashActivity.onCreate(SplashActivity.java:68)
    09-02 08:45:11.138: E/AndroidRuntime(6141):     at android.app.Activity.performCreate(Activity.java:6237)
    09-02 08:45:11.138: E/AndroidRuntime(6141):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107)
    09-02 08:45:11.138: E/AndroidRuntime(6141):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369)
    09-02 08:45:11.138: E/AndroidRuntime(6141):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
    09-02 08:45:11.138: E/AndroidRuntime(6141):     at android.app.ActivityThread.-wrap11(ActivityThread.java)
    09-02 08:45:11.138: E/AndroidRuntime(6141):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
    09-02 08:45:11.138: E/AndroidRuntime(6141):     at android.os.Handler.dispatchMessage(Handler.java:102)
    09-02 08:45:11.138: E/AndroidRuntime(6141):     at android.os.Looper.loop(Looper.java:148)
    09-02 08:45:11.138: E/AndroidRuntime(6141):     at android.app.ActivityThread.main(ActivityThread.java:5417)
    09-02 08:45:11.138: E/AndroidRuntime(6141):     at java.lang.reflect.Method.invoke(Native Method)
    09-02 08:45:11.138: E/AndroidRuntime(6141):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
    09-02 08:45:11.138: E/AndroidRuntime(6141):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

有谁知道这个问题的可能解决方案或至少是解决方法? 我正在努力寻找解决方案,但我无法理解问题所在。

今天,我在 Nexus 6(摩托罗拉)上使用 Android 6.0 测试我的应用程序时收到了相同的错误消息。我通过检查清单文件中的 targetSDKVersion 解决了我的问题。使用“22”而不是“23”作为 targetSDKVersion 解决了这个问题。 (见下文)

<uses-sdk
        android:minSdkVersion="15"
        android:targetSdkVersion="22" />

我还检查了 build.gradle 个文件的编译版本和 targetSDK 版本:

compileSdkVersion 22
    buildToolsVersion '22.0.1'

    defaultConfig {
        minSdkVersion 15
        targetSdkVersion 22
    }

希望对您有所帮助。然而,这只是目前的短期解决方法,不过我希望我们能从 metaio 得到一些反馈。

此致, 克里斯汀

我收到了来自 metaio 的 SDK 团队的反馈。他们说这个问题不能通过 metaio 轻松解决,因为它与 FFMpeg 库有关。我们不得不希望 FFMpeg 的更新能够解决这个问题。 我假设我们必须等待这样的更新并在应用程序中交换库文件。

我还没有寻找 FFMpeg 开发人员联系论坛来进行查询或通知错误。你是偶然认识的吗?

祝贺你,克里斯汀

如果要求加载带有文本重定位的共享库,Android 的先前版本会发出警告:

"libfoo.so has text relocations. This is wasting memory and prevents security hardening. Please fix.".

尽管如此,OS 仍会加载库。如果您的应用程序的目标 SDK 版本 >= 23,Marshmallow 将拒绝库。系统不再记录此信息,因为它假设您的应用程序将自己记录 dlopen(3) 失败,并包含来自 dlerror(3) 的文本,它确实解释了问题。不幸的是,在这种情况下,许多应用程序似乎捕获并隐藏了 UnsatisfiedLinkError throw by System.loadLibrary,通常不会留下库加载失败的线索,直到您尝试调用您的本机方法之一并且 VM 抱怨它不存在。

您可以使用命令行 scanelf 工具检查文本重定位。您可以在互联网上找到有关该主题的建议;例如 https://wiki.gentoo.org/wiki/Hardened/Textrels_Guide 是一个有用的指南。

好的,即使设置了 targetSDK 23,我也可以在这里工作。

对我和我的分支来说,需要修补的五个文件是

libavcodec\arm\fft_fixed_neon.S  
libavcodec\arm\fft_neon.S  
libavcodec\arm\fft_vfp.S   
libavcodec\arm\mlpdsp_armv5te.S  
libutil\arm\asm.S  

我从 https://github.com/FFmpeg/FFmpeg

中获取了最新的

您还需要在构建中的某处声明 HAVE_SECTION_DATA_REL_RO,以便 asm.S 中的宏使用动态重定位选项。

您可以通过这样做来检查您的共享库是否有文本重定位:

readelf -a path/to/yourlib.so | grep TEXTREL

如果它有文本重定位,它会显示如下内容:

0x00000016 (TEXTREL)                    0x0

如果是这种情况,您可以使用可用的 latest NDK version 重新编译您的共享库:

ndk-build -B -j 8

如果您再次检查,grep 命令将return 什么都没有。

经过长时间的努力和尝试以不同的方式编译 FFmpeg,我找到了解决方案。确保使用 --disable-asm 标志编译 FFmpeg。这将确保 FFmpeg 不会有文本重定位,并且在针对 Android M (SDK 23)

编译时不会崩溃

为确保它有效,您可以使用上面提到的 readelf。

干杯