博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
解读Nativebridge对于houdin的支持
阅读量:2344 次
发布时间:2019-05-10

本文共 4566 字,大约阅读时间需要 15 分钟。

二、应用程序在加载so文件时的变化

原本功能是在javaVMExt::LoadNativeLibrary函数中实现的

(art\runtime\jin_internal.cc文件中):
该函数正常情况下使用dlopen打开so文件,但当x86系统试图打开arm版本的so ,返回错误时,这时就会使用NativeBridge自带的加载过程。

bool JavaVMExt::LoadNativeLibrary(const std::string& path,                                  Handle
class_loader, std::string* detail) { ...... const char* path_str = path.empty() ? nullptr : path.c_str(); void* handle = dlopen(path_str, RTLD_LAZY); bool needs_native_bridge = false; if (handle == nullptr) { if (android::NativeBridgeIsSupported(path_str)) { handle = android::NativeBridgeLoadLibrary(path_str, RTLD_LAZY); needs_native_bridge = true; } } ...... bool created_library = false; { MutexLock mu(self, libraries_lock); library = libraries->Get(path); if (library == nullptr) { // We won race to get libraries_lock library = new SharedLibrary(path, handle, class_loader.Get()); libraries->Put(path, library); created_library = true; } } ...... bool was_successful = false; void* sym = nullptr; if (UNLIKELY(needs_native_bridge)) { library->SetNeedsNativeBridge(); sym = library->FindSymbolWithNativeBridge("JNI_OnLoad", nullptr); } else { sym = dlsym(handle, "JNI_OnLoad"); } ......}

android::NativeBridgeRuntimeCallbacks

android::NativeBridgeCallbacks全局变量

callbacks->isSupportedcallbacks->loadLibrary(libpath, flag)callbacks->getTrampoline

一、对于部分NativeBridge源代码的更改

“ro.dalvik.vm.native.bridge” 指定动态链接库

  1. 有自己的数据目录,一般应用程序是有的,在/data/data/目录下。

如果决定要启用NativeBridge,则还需要调用android::PreInitializeNativeBridge对其做预初始化:

2)android.os.Build.SUPPORTED_ABIS,

更正过的

struct NativeBridgeCallbacks {  // Version number of the interface.  uint32_t version;  bool (*initialize)(const NativeBridgeRuntimeCallbacks* runtime_cbs, const char* private_dir,                     const char* instruction_set);  void* (*loadLibrary)(const char* libpath, int flag);  void* (*getTrampoline)(void* handle, const char* name, const char* shorty, uint32_t len);  bool (*isSupported)(const char* libpath);  const struct NativeBridgeRuntimeValues* (*getAppEnv)(const char* instruction_set);  bool (*isCompatibleWith)(uint32_t bridge_version);  NativeBridgeSignalHandlerFn (*getSignalHandler)(int signal);};

多出两个函数一个叫做isCompatibleWith,一个叫做getSignalHandler。

3)persist.sys.nativebridge系统属性设置为1
4)ro.product.cpu.abilist系统属性
这个属性会控制特定版本的系统可以安装的app类型,为了是x86系统可以安装只包含arm指令集的apk,我没就需要更改这个属性。
ro.product.cpu.abilist=x86,armeabi-v7a,armeabi
ro.product.cpu.abilisit32=x86,armeabi-v7a,armeabi
5)ro.dalvik.vm.isa.arm系统属性(Android-X86系统中的build.prop)
ro.dalvik.vm.isa.arm=x86
ro.dalvik.vm.isa.=

其他更改部分

看了半天发现好像剩下的只剩

而原始NativeBridgeCallbacks结构体的定义如下(代码位于system\core\include\nativebridge\native_bridge.h文件中):

struct NativeBridgeCallbacks {  uint32_t version;  bool (*initialize)(const NativeBridgeRuntimeCallbacks* runtime_cbs, const char* private_dir,                     const char* instruction_set);  void* (*loadLibrary)(const char* libpath, int flag);  void* (*getTrampoline)(void* handle, const char* name, const char* shorty, uint32_t len);  bool (*isSupported)(const char* libpath);  const struct NativeBridgeRuntimeValues* (*getAppEnv)(const char* instruction_set);};

但这里的实现却是在libnb.so里面,。所以,这个所谓的nativebridge本质上就是实现以上几个接口后实现的功能。

system的native_bridge.cpp通过外部实现的这几个接口来传递编码转换的初始化函数。

总结:

libnb里面有7个回调接口,原本native_bridge.cpp里面只利用了5个,为了增加houdin我们利用增加的在native_bridge里面做了检查和信号处理。
getsignalHandler利用在这里调用这个函数的地方在这里(代码位于art\runtime\native_bridge_art_interface.cc文件中):

void InitializeNativeBridge(JNIEnv* env, const char* instruction_set) {  if (android::InitializeNativeBridge(env, instruction_set)) {    if (android::NativeBridgeGetVersion() >= 2U) {#ifdef _NSIG      for (int signal = 0; signal < _NSIG; ++signal) {        android::NativeBridgeSignalHandlerFn fn = android::NativeBridgeGetSignalHandler(signal);        if (fn != nullptr) {          SetSpecialSignalHandlerFn(signal, fn);        }      }#endif    }  }}

最后函数就会利用getTrampoline跳到转化指令集里面执行。

不过有一点还不清楚,那就是绑定指定程序执行的操作有啥用。先不管了。

android 5.0 具体变化文件:

art/runtime/sigchainlib/sigchain_dummy.cc 、 、 sigchain.h
art/runtime/jni_internal.cc 、 native_bridge_art_interface.cc 、native_bridge_art_interaface.h

libnb.so位置      device/generic/common/nativebridge/native_bridge.cc 位于、system/core/libnativebridge/native_bridge.cc

结果

经过对代码的不断跟踪和错误修正,最终结果如下:

在这里插入图片描述
我们这仅仅是编译了简单的jni函数,实现了native层的hello world但根据日志中显示加载文件为arm/libplthook-lib.so
可以看出我们成功的执行了arm指令下的so文件中的字符串转换。并且我们编译的程序so库中只包含arm指令,没有x86的so。感兴趣的同学可以自己试试。

并且,那个标定指令

这一部分的东西并没什么卵用,因为我到这里根本没有设置相应的文件。

大功告成。

学习源码这么长时间,第一次添加自己的逻辑,感觉不错。哈哈哈哈

转载地址:http://dvjvb.baihongyu.com/

你可能感兴趣的文章
1022. Fib数列
查看>>
一些开源项目
查看>>
将博客搬至CSDN
查看>>
MySQL 中事务的实现
查看>>
CheckStyle
查看>>
IDE配置jvm参数
查看>>
内存溢出
查看>>
Spring Cloud 声明式服务调用 Feign
查看>>
JVM实用参数(一)JVM类型以及编译器模式
查看>>
spring cloud config 属性加解密
查看>>
rabbitmq安装
查看>>
RabbitMQ 使用
查看>>
动态代理
查看>>
oracle中merge into用法解析
查看>>
MySQL Explain详解
查看>>
oracle性能监控
查看>>
Spring Boot 整合Servlet
查看>>
Spring Boot 整合Filter
查看>>
nginx 安装
查看>>
ngnix 详解
查看>>