android studio ndk/so笔记

本文介绍了如何解决在Android 6.0及以上版本中遇到的UnsatisfiedLinkError:dlopen failed.textrelocations问题,并提供了两种解决方案。

1. 如何使用第三方so库如何使用第三方so库? 

 在app的build.gradle中加入

android { 
    sourceSets { 
        main { 
            jniLibs.srcDirs = ['libs'] 
             } 
    } 
    //如下语句用于指定apk只生成指定cpu架构的so文件夹 
    ndk { 
        abiFilters "armeabi", "armeabi-v7a", "x86", "mips" 
    } 
}复制代码


2. android6.0以上报错UnsatisfiedLinkError: dlopen failed . text relocations

   在使用libserial_port 库时,在android5.1上运行正常,但当移植到7.0上时出现                  UnsatisfiedLinkError: dlopen failed . text relocations

  • 这个问题出现在loadLibrary()的过程中.
  •  在Android 6.0之前, text reloactions问题, 会在编译的过程中, 作为warning报出来, log大致如下:

    ActivityManager: WARNING: linker: libdvm.so has text relocations. This is wasting memory and is a security risk. Please fix.
    复制代码

      在Android 6.0中, 原来的warning被升级为error了. 因此, 同样的库文件, 在Android 6.0前的 环境运行, 不报错, 6.0下就会crash掉.

  •  text reloactions又被称为TEXTREL, 它与PIC相关, 先说PIC:

       PIC: Position Independent Code, 指一段代码, 在加载到内存后, 其物理地址与代码本身是无关的.

      为什么要使用PIC:

     1. 效率相关: 使用PIC后, 代码可以被加载到内存的任意位置, 即不存在某段代码始终对应特定物理地址的情况, 这样的方式, 适用于共享对象的加载.

换个说法, 使用PIC的共享对象, 在内存中是真正"共享"的; 而未使用PIC的共享对象, 在被不同进程加载的过程中, 会产生多个copy, 从而引入效率问题.

    2. 安全相关: 使用PIC后, 特定代码被加载的内存地址不确定, 这样可以避免某些内存地址敏感的攻击. RedHat有一篇相关的文章: securityblog.redhat.com/2012/11/28/…,回到TEXTREL, 它实际上是源码中存在"特定代码映射特定地址". 加载代码时, 必须将其加载到特定物理地址, 导致调用这些代码时, 必需增加一个relocation的过程.

解决方案:

方案一 :

把targetSdkVersion设为小于23,这样是可以回避掉上述问题,但只是治标不治本。

方案二 (简单但会影响程序效率):

在使用NDK编译so时配置Android.mk,增添PIC相关的配置项,这样编译出来的so文件将不再有text relocations的问题。具体配置如下:

LOCAL_LDFLAGS += -fPIC
复制代码

PIC参数用于编译位置无关代码,生成可用于共享库的位置独立代码。若不添加-fPIC,则加载so文件的代码段时,代码段引用的数据对象需要重定位,重定位会修改代码段内容,这样就导致没使用这个so文件,代码段的进程在内核中就会生成这个文件的拷贝。

参考文章:libxxx.so- text relocations问题的终极解决方案



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值