自定义linker踩坑记录
自定义linker踩坑记录
1.需求描述
众所周知linker是Android系统中实现动态链接的程序,存放在路径/apex/com.android.runtime/bin/linker64,现在我想把linker链接过的so库dump到本地,那就需要对linker的代码进行修改,添加dump代码。
2.实现方法
首先我想到的是直接在linker的代码中添加dump代码,比如dlopen等函数,等它链接完,我就根据返回的soinfo信息(包含起始和终止地址)来dump一下。
但遇到的问题是,我无法区分要dump的so以及dump的时候,文件系统可能还未初始化好,此时我调用getuid()等函数也是失败了。
这时候我的实现方法变为:在linker中添加接口,然后我在nativeLoad调用的时候我再dump(nativeLoad是System.loadlibrary()最终调用的native函数)。这样只有Java层主动加载的so库才会被dump。
3.(踩坑)过程记录(基于AOSP10)
(1)首先,我们应该梳理一下代码的调用关系,以及库的依赖关系
nativeLoad声明在libcore/ojluni/src/main/java/java/lang/Runtime.java
1 | |
然后其native层实现在libcore/ojluni/src/main/native/Runtime.c(编译到`libcore/NativeCode.bp中的libopenjdk)
1 | |
JVM_NativeLoad的实现在art/openjdkjvm/OpenjdkJvm.cc(编译到art/openjdkjvm/Android.bp中的libopenjdkjvm)
1 | |
LoadNativeLibrary的实现在art/runtime/jni/java_vm_ext.cc(编译到libart.so里art/runtime/Android.bp)
1 | |
OpenNativeLibrary的实现在system/core/libnativeloader/native_loader.cpp
1 | |
android_dlopen_ext声明在android/dlext.h中,并通过system/core/libnativeloader/include/nativeloader/dlext_namespaces.h间接include
1 | |
而android_dlopen_ext在bionic/libdl/libdl.cpp中实现
1 | |
同时还在此文件中声明原型
1 | |
还需要在bionic/libdl/libdl.map.txt中声明接口(坑点)
1 | |
以下开始linker部分
在bionic/linker/dlfcn.cpp声明__loader_android_dlopen_ext原型
1 | |
实现
1 | |
在bionic/linker/ld_android.cpp中写下(不写libdl.so无法链接到linker)
1 | |
除此之外还需要在bionic/linker/linker.arm.map和bionic/linker/linker.generic.map分别写:
1 | |
和
1 | |
(2)从linker中导出solist_get_head()给nativLoader.so用
linker和ld-android部分
首先在bionic/linker/dlfcn.cpp中include头文件
1 | |
然后在extern "C"中添加导出接口声明
1 | |
定义:
1 | |
然后bionic/linker/ld_android.cpp中添加
1 | |
然后bionic/linker/linker.arm.map和bionic/linker/linker.generic.map中均添加
1 | |
libdl部分
在bionic/libdl/libdl.cpp中添加
1 | |
和
1 | |
并在头文件bionic/libc/include/android/dlext.h中添加get_head函数声明
1 | |
然后在system/core/libnativeloader/native_loader.cpp的OpenNativeLibrary函数中使用get_head函数进行测试
1 | |
效果展示:
(3)库依赖分析
上面我们算是把需求实现了,这其中之所以这么麻烦,是因为每部分都是在单独的库里,然后通过动态链接来引用/调用的,如果都是在同一个库里,那直接include头文件然后调用就可以了,如果链接不对,通常是使用的函数所在库没有正确导出这个符号。
nativeloader
system/core/libnativeloader/Android.bp
1 | |
libdl
bionic/libdl/Android.bp
1 | |
ld-android
1 | |
linker
1 | |