自定义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 |
|