替换Android中VM 加载动态库方式

Android加载动态库的代码在 dalvik/vm/Native.c,加载的方式就是调用 libdl 中 dlopen, dlsym 这些函数

应该可以在这些函数中做些手脚,dlsym 替换为 my_dlsym 这样就可以调用自己的函数

下面举一个例子,通常 dlopen, dlsym 使用如下

#include <dlfcn.h>
void* handle = dlopen("./hello.so", RTLD_LAZY);
typedef void (*hello_t)();
hello_t hello = (hello_t) dlsym(handle, "hello");
 hello();
dlclose(handle);</dlfcn.h>

 

我们把在另外一个 hello1.so 提供 hello1()

#include <dlfcn.h>
void* handle = dlopen("./hello1.so", RTLD_LAZY);
typedef void (*hello_t)();
hello_t hello = (hello_t) dlsym(handle, "hello1");
 hello();
dlclose(handle);
</dlfcn.h>

用户依然可以得到他想要 hello 指针

同理 在 Native.c 中定义

extern void *my_dlopen(const char *filename, int flag);
extern char *my_dlerror(void);
extern void *my_dlsym(void *handle, const char *symbol);
extern int my_dlclose(void *handle);

并把 Native.c 相关函数,加上前缀 my_, 就完全改变了 VM load 动态库的方式

这种方式可以有多种应用方式,下面举个栗子

比如你想做 profiling, 比如 func()

my_func() {
      // instrument code
       func()
}

而后在 my_dlsym 把对 symbol “func” 的调用替换为 my_func(), 就可以了

也许你说可以直接改 func(); 但当函数多的时候,可以在 my_dlsym中构造数组更方便解决

也许你可以把对 bionic 调用,全部替换为 glibc 的,但要注意 data struct 定义的不同,inline 和 宏定义

分享到:

发表评论

昵称

沙发空缺中,还不快抢~