forked from rovo89/Xposed
-
Notifications
You must be signed in to change notification settings - Fork 0
/
libxposed_art.cpp
163 lines (136 loc) · 5.09 KB
/
libxposed_art.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
/**
* This file includes functions specific to the ART runtime.
*/
#define LOG_TAG "Xposed"
#include "xposed_shared.h"
#include "libxposed_common.h"
#include "fd_utils-inl.h"
#include "thread.h"
#include "common_throws.h"
#if PLATFORM_SDK_VERSION >= 23
#include "art_method-inl.h"
#else
#include "mirror/art_method-inl.h"
#endif
#include "mirror/object-inl.h"
#include "mirror/throwable.h"
#include "native/scoped_fast_native_object_access.h"
#include "reflection.h"
#include "scoped_thread_state_change.h"
#include "well_known_classes.h"
using namespace art;
#if PLATFORM_SDK_VERSION < 23
using art::mirror::ArtMethod;
#endif
namespace xposed {
////////////////////////////////////////////////////////////
// Library initialization
////////////////////////////////////////////////////////////
/** Called by Xposed's app_process replacement. */
bool xposedInitLib(XposedShared* shared) {
xposed = shared;
xposed->onVmCreated = &onVmCreatedCommon;
return true;
}
/** Called very early during VM startup. */
bool onVmCreated(JNIEnv*) {
// TODO: Handle CLASS_MIUI_RESOURCES?
ArtMethod::xposed_callback_class = classXposedBridge;
ArtMethod::xposed_callback_method = methodXposedBridgeHandleHookedMethod;
return true;
}
////////////////////////////////////////////////////////////
// Utility methods
////////////////////////////////////////////////////////////
void logExceptionStackTrace() {
Thread* self = Thread::Current();
#if PLATFORM_SDK_VERSION >= 23
XLOG(ERROR) << self->GetException()->Dump();
#else
XLOG(ERROR) << self->GetException(nullptr)->Dump();
#endif
}
/** Lay the foundations for XposedBridge.setObjectClassNative() */
void prepareSubclassReplacement(JNIEnv* env, jclass clazz) {
// clazz is supposed to replace its superclass, so make sure enough memory is allocated
ScopedObjectAccess soa(env);
mirror::Class* sub = soa.Decode<mirror::Class*>(clazz);
mirror::Class* super = sub->GetSuperClass();
super->SetObjectSize(sub->GetObjectSize());
}
////////////////////////////////////////////////////////////
// JNI methods
////////////////////////////////////////////////////////////
void XposedBridge_hookMethodNative(JNIEnv* env, jclass, jobject javaReflectedMethod,
jobject, jint, jobject javaAdditionalInfo) {
// Detect usage errors.
if (javaReflectedMethod == nullptr) {
#if PLATFORM_SDK_VERSION >= 23
ThrowIllegalArgumentException("method must not be null");
#else
ThrowIllegalArgumentException(nullptr, "method must not be null");
#endif
return;
}
// Get the ArtMethod of the method to be hooked.
ScopedObjectAccess soa(env);
ArtMethod* artMethod = ArtMethod::FromReflectedMethod(soa, javaReflectedMethod);
// Hook the method
artMethod->EnableXposedHook(soa, javaAdditionalInfo);
}
jobject XposedBridge_invokeOriginalMethodNative(JNIEnv* env, jclass, jobject javaMethod,
jint isResolved, jobjectArray, jclass, jobject javaReceiver, jobjectArray javaArgs) {
ScopedFastNativeObjectAccess soa(env);
if (UNLIKELY(!isResolved)) {
ArtMethod* artMethod = ArtMethod::FromReflectedMethod(soa, javaMethod);
if (LIKELY(artMethod->IsXposedHookedMethod())) {
javaMethod = artMethod->GetXposedHookInfo()->reflectedMethod;
}
}
#if PLATFORM_SDK_VERSION >= 23
return InvokeMethod(soa, javaMethod, javaReceiver, javaArgs);
#else
return InvokeMethod(soa, javaMethod, javaReceiver, javaArgs, true);
#endif
}
void XposedBridge_setObjectClassNative(JNIEnv* env, jclass, jobject javaObj, jclass javaClazz) {
ScopedObjectAccess soa(env);
mirror::Class* clazz = soa.Decode<mirror::Class*>(javaClazz);
StackHandleScope<1> hs(soa.Self());
Handle<mirror::Class> c(hs.NewHandle(clazz));
#if PLATFORM_SDK_VERSION >= 23
if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(soa.Self(), c, true, true)) {
#else
if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c, true, true)) {
#endif
XLOG(ERROR) << "Could not initialize class " << PrettyClass(clazz);
return;
}
mirror::Object* obj = soa.Decode<mirror::Object*>(javaObj);
obj->SetClass(clazz);
}
void XposedBridge_dumpObjectNative(JNIEnv*, jclass, jobject) {
// TODO Can be useful for debugging
UNIMPLEMENTED(ERROR|LOG_XPOSED);
}
jobject XposedBridge_cloneToSubclassNative(JNIEnv* env, jclass, jobject javaObject, jclass javaClazz) {
ScopedObjectAccess soa(env);
mirror::Object* obj = soa.Decode<mirror::Object*>(javaObject);
mirror::Class* clazz = soa.Decode<mirror::Class*>(javaClazz);
mirror::Object* dest = obj->Clone(soa.Self(), clazz->GetObjectSize());
dest->SetClass(clazz);
return soa.AddLocalReference<jobject>(dest);
}
jint XposedBridge_getRuntime(JNIEnv*, jclass) {
return 2; // RUNTIME_ART
}
static FileDescriptorTable* gClosedFdTable = NULL;
void XposedBridge_closeFilesBeforeForkNative(JNIEnv*, jclass) {
gClosedFdTable = FileDescriptorTable::Create();
}
void XposedBridge_reopenFilesAfterForkNative(JNIEnv*, jclass) {
gClosedFdTable->Reopen();
delete gClosedFdTable;
gClosedFdTable = NULL;
}
} // namespace xposed