/
/
/
/
Created by Zhenxi on
2022
/
8
/
22.
/
/
static void
*
art_method_register
=
nullptr;
static void
*
class_linker_
=
nullptr;
size_t OffsetOfJavaVm(
bool
has_small_irt,
int
SDK_INT) {
if
(has_small_irt) {
switch (SDK_INT) {
case ANDROID_T:
case ANDROID_SL:
case ANDROID_S:
return
sizeof(void
*
)
=
=
8
?
624
:
300
;
case ANDROID_R:
case ANDROID_Q:
return
sizeof(void
*
)
=
=
8
?
528
:
304
;
default:
LOGE(
"OffsetOfJavaVM Unexpected android version %d"
, SDK_INT);
abort();
}
}
else
{
switch (SDK_INT) {
case ANDROID_T:
case ANDROID_SL:
case ANDROID_S:
return
sizeof(void
*
)
=
=
8
?
520
:
300
;
case ANDROID_R:
case ANDROID_Q:
return
sizeof(void
*
)
=
=
8
?
496
:
288
;
default:
LOGE(
"OffsetOfJavaVM Unexpected android version %d"
, SDK_INT);
abort();
}
}
}
template<typename T>
int
findOffset(void
*
start, size_t
len
, size_t step, T value) {
if
(nullptr
=
=
start) {
return
-
1
;
}
for
(
int
i
=
0
; i <
=
len
; i
+
=
step) {
T current_value
=
*
reinterpret_cast<T
*
>((size_t) start
+
i);
if
(value
=
=
current_value) {
return
i;
}
}
return
-
1
;
}
/
*
*
*
根据runtime获取class_linker
*
https:
/
/
github.com
/
magician8520
/
BlackBox
/
blob
/
99f26925aa303fd0a71543e3713ef3fc57a08e81
/
Bcore
/
pine
-
core
/
src
/
main
/
cpp
/
android.h
*
/
void
*
getClassLinker() {
if
(class_linker_ !
=
nullptr) {
return
class_linker_;
}
int
SDK_INT
=
get_sdk_level();
/
/
If SmallIrtAllocator symbols can be found, then the ROM has merged commit
"Initially allocate smaller local IRT"
/
/
This commit added a pointer member between `class_linker_`
and
`java_vm_`. Need to calibrate offset here.
/
/
https:
/
/
android.googlesource.com
/
platform
/
art
/
+
/
4dcac3629ea5925e47b522073f3c49420e998911
/
/
https:
/
/
github.com
/
crdroidandroid
/
android_art
/
commit
/
aa7999027fa830d0419c9518ab56ceb7fcf6f7f1
bool
has_smaller_irt
=
getSymCompat(getlibArtPath(),
"_ZN3art17SmallIrtAllocator10DeallocateEPNS_8IrtEntryE"
) !
=
nullptr;
size_t jvm_offset
=
OffsetOfJavaVm(has_smaller_irt, SDK_INT);
auto runtime_instance_
=
*
reinterpret_cast<void
*
*
>
(getSymCompat(getlibArtPath(),
"_ZN3art7Runtime9instance_E"
));
auto val
=
jvm_offset
? reinterpret_cast<std::unique_ptr<JavaVM>
*
>(
reinterpret_cast<uintptr_t>(runtime_instance_)
+
jvm_offset)
-
>get()
: nullptr;
if
(val
=
=
getVm()) {
LOGD(
"JavaVM offset matches the default offset"
);
}
else
{
LOGW(
"JavaVM offset mismatches the default offset, try search the memory of Runtime"
);
int
offset
=
findOffset(runtime_instance_,
1024
,
4
, getVm());
if
(offset
=
=
-
1
) {
LOGE(
"Failed to find java vm from Runtime"
);
return
nullptr;
}
jvm_offset
=
offset;
LOGW(
"Found JavaVM in Runtime at %zu"
, jvm_offset);
}
const size_t kDifference
=
has_smaller_irt
? sizeof(std::unique_ptr<void>)
+
sizeof(void
*
)
*
3
: SDK_INT
=
=
ANDROID_Q
? sizeof(void
*
)
*
2
: sizeof(std::unique_ptr<void>)
+
sizeof(void
*
)
*
2
;
class_linker_
=
*
reinterpret_cast<void
*
*
>(reinterpret_cast<uintptr_t>(runtime_instance_)
+
jvm_offset
-
kDifference);
return
class_linker_;
}
bool
call_MethodRegister(JNIEnv
*
env, void
*
art_method, void
*
native_method) {
if
(art_method_register
=
=
nullptr) {
if
(get_sdk_level() < ANDROID_S) {
/
/
android
11
art_method_register
=
getSymCompat(getlibArtPath(),
"_ZN3art9ArtMethod14RegisterNativeEPKv"
);
if
(art_method_register
=
=
nullptr) {
art_method_register
=
getSymCompat(getlibArtPath(),
"_ZN3art9ArtMethod14RegisterNativeEPKvb"
);
}
}
else
{
/
/
12
以上还是在libart里面,但是在linker里面实现,符号名称存在变化
art_method_register
=
getSymCompat(getlibArtPath(),
"_ZN3art11ClassLinker14RegisterNativeEPNS_6ThreadEPNS_9ArtMethodEPKv"
);
}
if
(art_method_register
=
=
nullptr) {
LOG(ERROR) <<
"register native method get art_method_register = null "
;
return
false;
}
}
if
(get_sdk_level() >
=
ANDROID_S) {
/
/
12
以上
/
/
const void
*
RegisterNative(Thread
*
self
, ArtMethod
*
method, const void
*
native_method)
auto call
=
reinterpret_cast<void
*
(
*
)(void
*
, void
*
, void
*
,
void
*
)>(art_method_register);
/
/
get
self
thread
void
*
self
=
getSymCompat(getlibArtPath(),
"_ZN3art6Thread14CurrentFromGdbEv"
);
if
(
self
=
=
nullptr) {
LOG(ERROR) <<
"register native method get CurrentFromGdb = null "
;
return
false;
}
/
/
手动计算一下linker实例地址
void
*
classLinker
=
getClassLinker();
if
(classLinker
=
=
nullptr) {
LOG(ERROR) <<
"register native method get getClassLinker = null "
;
return
false;
}
call(classLinker,
self
, art_method, native_method);
/
/
LOG(ERROR) <<
"register native method get getClassLinker success! "
;
}
else
if
(get_sdk_level() >
=
ANDROID_R) {
auto call
=
reinterpret_cast<void
*
(
*
)(void
*
, void
*
)>(art_method_register);
call(art_method, native_method);
}
else
{
auto call
=
reinterpret_cast<void
*
(
*
)(void
*
, void
*
,
bool
)>(art_method_register);
call(art_method, native_method, true);
}
return
true;
}
inline static
bool
IsIndexId(jmethodID mid) {
return
((reinterpret_cast<uintptr_t>(mid)
%
2
) !
=
0
);
}
static jfieldID field_art_method
=
nullptr;
bool
RegisterNativeMethod(JNIEnv
*
env,
jclass clazz,
const JNINativeMethod
*
methods,
size_t nMethods) {
if
(env
=
=
nullptr) {
LOG(ERROR) <<
"register native method JNIEnv = null "
;
return
false;
}
void
*
arm_method
=
nullptr;
for
(
int
i
=
0
; i < nMethods; i
+
+
) {
jmethodID methodId
=
env
-
>GetMethodID(clazz, methods[i].name, methods[i].signature);
if
(methodId
=
=
nullptr) {
/
/
maybe static
env
-
>ExceptionClear();
methodId
=
env
-
>GetStaticMethodID(clazz, methods[i].name, methods[i].signature);
if
(methodId
=
=
nullptr) {
LOG(ERROR) <<
"register native method get orig method == null "
<< methods[i].signature;
env
-
>ExceptionClear();
return
false;
}
}
if
(get_sdk_level() >
=
ANDROID_R) {
if
(field_art_method
=
=
nullptr) {
jclass pClazz
=
env
-
>FindClass(
"java/lang/reflect/Executable"
);
field_art_method
=
env
-
>GetFieldID(pClazz,
"artMethod"
,
"J"
);
}
if
(field_art_method
=
=
nullptr) {
LOG(ERROR) <<
"register native method get artMethod == null "
;
return
false;
}
if
(IsIndexId(methodId)) {
jobject method
=
env
-
>ToReflectedMethod(clazz, methodId, true);
arm_method
=
reinterpret_cast<void
*
>(env
-
>GetLongField(method, field_art_method));
/
/
LOG(ERROR) <<
"arm_method "
<<arm_method ;
}
}
else
{
arm_method
=
methodId;
}
if
(arm_method
=
=
nullptr) {
LOG(ERROR) <<
"register native method art method == null "
;
return
false;
}
if
(!call_MethodRegister(env, arm_method, methods[i].fnPtr)) {
LOG(ERROR) <<
"register native method fail "
<<
methods[i].name <<
" "
<< methods[i].signature;
return
false;
}
/
/
LOG(INFO) <<
"register native method success "
<< methods[i].name <<
" "
/
/
<< methods[i].signature;
}
return
true;
}