代码拉取完成,页面将自动刷新
同步操作将从 Gitee 极速下载/xposed 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
/**
* This file includes functions specific to the Dalvik runtime.
*/
#define LOG_TAG "Xposed"
#include "libxposed_dalvik.h"
#include "xposed_offsets.h"
#include <dlfcn.h>
namespace xposed {
////////////////////////////////////////////////////////////
// Forward declarations
////////////////////////////////////////////////////////////
bool initMemberOffsets(JNIEnv* env);
void hookedMethodCallback(const u4* args, JValue* pResult, const Method* method, ::Thread* self);
void XposedBridge_invokeOriginalMethodNative(const u4* args, JValue* pResult, const Method* method, ::Thread* self);
////////////////////////////////////////////////////////////
// Variables
////////////////////////////////////////////////////////////
static ClassObject* objectArrayClass = NULL;
static size_t arrayContentsOffset = 0;
static void* PTR_gDvmJit = NULL;
////////////////////////////////////////////////////////////
// Library initialization
////////////////////////////////////////////////////////////
/** Called by Xposed's app_process replacement. */
bool xposedInitLib(xposed::XposedShared* shared) {
xposed = shared;
xposed->onVmCreated = &onVmCreatedCommon;
return true;
}
/** Called very early during VM startup. */
bool onVmCreated(JNIEnv* env) {
if (!initMemberOffsets(env))
return false;
jclass classMiuiResources = env->FindClass(CLASS_MIUI_RESOURCES);
if (classMiuiResources != NULL) {
ClassObject* clazz = (ClassObject*)dvmDecodeIndirectRef(dvmThreadSelf(), classMiuiResources);
if (dvmIsFinalClass(clazz)) {
ALOGD("Removing final flag for class '%s'", CLASS_MIUI_RESOURCES);
clazz->accessFlags &= ~ACC_FINAL;
}
}
env->ExceptionClear();
Method* xposedInvokeOriginalMethodNative = (Method*) env->GetStaticMethodID(classXposedBridge, "invokeOriginalMethodNative",
"(Ljava/lang/reflect/Member;I[Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;");
if (xposedInvokeOriginalMethodNative == NULL) {
ALOGE("ERROR: could not find method %s.invokeOriginalMethodNative(Member, int, Class[], Class, Object, Object[])", CLASS_XPOSED_BRIDGE);
dvmLogExceptionStackTrace();
env->ExceptionClear();
return false;
}
dvmSetNativeFunc(xposedInvokeOriginalMethodNative, XposedBridge_invokeOriginalMethodNative, NULL);
objectArrayClass = dvmFindArrayClass("[Ljava/lang/Object;", NULL);
if (objectArrayClass == NULL) {
ALOGE("Error while loading Object[] class");
dvmLogExceptionStackTrace();
env->ExceptionClear();
return false;
}
return true;
}
bool initMemberOffsets(JNIEnv* env) {
PTR_gDvmJit = dlsym(RTLD_DEFAULT, "gDvmJit");
if (PTR_gDvmJit == NULL) {
offsetMode = MEMBER_OFFSET_MODE_NO_JIT;
} else {
offsetMode = MEMBER_OFFSET_MODE_WITH_JIT;
}
ALOGD("Using structure member offsets for mode %s", xposedOffsetModesDesc[offsetMode]);
MEMBER_OFFSET_COPY(DvmJitGlobals, codeCacheFull);
int overrideCodeCacheFull = readIntConfig(XPOSED_OVERRIDE_JIT_RESET_OFFSET, -1);
if (overrideCodeCacheFull > 0 && overrideCodeCacheFull < 0x400) {
ALOGI("Offset for DvmJitGlobals.codeCacheFull is overridden, new value is 0x%x", overrideCodeCacheFull);
MEMBER_OFFSET_VAR(DvmJitGlobals, codeCacheFull) = overrideCodeCacheFull;
}
// detect offset of ArrayObject->contents
jintArray dummyArray = env->NewIntArray(1);
if (dummyArray == NULL) {
ALOGE("Could allocate int array for testing");
dvmLogExceptionStackTrace();
env->ExceptionClear();
return false;
}
jint* dummyArrayElements = env->GetIntArrayElements(dummyArray, NULL);
arrayContentsOffset = (size_t)dummyArrayElements - (size_t)dvmDecodeIndirectRef(dvmThreadSelf(), dummyArray);
env->ReleaseIntArrayElements(dummyArray,dummyArrayElements, 0);
env->DeleteLocalRef(dummyArray);
if (arrayContentsOffset < 12 || arrayContentsOffset > 128) {
ALOGE("Detected strange offset %d of ArrayObject->contents", arrayContentsOffset);
return false;
}
return true;
}
////////////////////////////////////////////////////////////
// Utility methods
////////////////////////////////////////////////////////////
/** Portable clone of dvmSetObjectArrayElement() */
inline void setObjectArrayElement(const ArrayObject* obj, int index, Object* val) {
uintptr_t arrayContents = (uintptr_t)obj + arrayContentsOffset;
((Object **)arrayContents)[index] = val;
dvmWriteBarrierArray(obj, index, index + 1);
}
/** Wrapper used by the common part of the library. */
void logExceptionStackTrace() {
dvmLogExceptionStackTrace();
}
/** Check whether a method is already hooked. */
inline bool isMethodHooked(const Method* method) {
return (method->nativeFunc == &hookedMethodCallback);
}
////////////////////////////////////////////////////////////
// JNI methods
////////////////////////////////////////////////////////////
/** This is called when a hooked method is executed. */
void hookedMethodCallback(const u4* args, JValue* pResult, const Method* method, ::Thread* self) {
if (!isMethodHooked(method)) {
dvmThrowNoSuchMethodError("Could not find Xposed original method - how did you even get here?");
return;
}
XposedHookInfo* hookInfo = (XposedHookInfo*) method->insns;
Method* original = (Method*) hookInfo;
Object* originalReflected = hookInfo->reflectedMethod;
Object* additionalInfo = hookInfo->additionalInfo;
// convert/box arguments
const char* desc = &method->shorty[1]; // [0] is the return type.
Object* thisObject = NULL;
size_t srcIndex = 0;
size_t dstIndex = 0;
// for non-static methods determine the "this" pointer
if (!dvmIsStaticMethod(original)) {
thisObject = (Object*) args[0];
srcIndex++;
}
ArrayObject* argsArray = dvmAllocArrayByClass(objectArrayClass, strlen(method->shorty) - 1, ALLOC_DEFAULT);
if (argsArray == NULL) {
return;
}
while (*desc != '\0') {
char descChar = *(desc++);
JValue value;
Object* obj;
switch (descChar) {
case 'Z':
case 'C':
case 'F':
case 'B':
case 'S':
case 'I':
value.i = args[srcIndex++];
obj = (Object*) dvmBoxPrimitive(value, dvmFindPrimitiveClass(descChar));
dvmReleaseTrackedAlloc(obj, self);
break;
case 'D':
case 'J':
value.j = dvmGetArgLong(args, srcIndex);
srcIndex += 2;
obj = (Object*) dvmBoxPrimitive(value, dvmFindPrimitiveClass(descChar));
dvmReleaseTrackedAlloc(obj, self);
break;
case '[':
case 'L':
obj = (Object*) args[srcIndex++];
break;
default:
ALOGE("Unknown method signature description character: %c", descChar);
obj = NULL;
srcIndex++;
}
setObjectArrayElement(argsArray, dstIndex++, obj);
}
// call the Java handler function
JValue result;
dvmCallMethod(self, (Method*) methodXposedBridgeHandleHookedMethod, NULL, &result,
originalReflected, (int) original, additionalInfo, thisObject, argsArray);
dvmReleaseTrackedAlloc(argsArray, self);
// exceptions are thrown to the caller
if (dvmCheckException(self)) {
return;
}
// return result with proper type
ClassObject* returnType = dvmGetBoxedReturnType(method);
if (returnType->primitiveType == PRIM_VOID) {
// ignored
} else if (result.l == NULL) {
if (dvmIsPrimitiveClass(returnType)) {
dvmThrowNullPointerException("null result when primitive expected");
}
pResult->l = NULL;
} else {
if (!dvmUnboxPrimitive(result.l, returnType, pResult)) {
dvmThrowClassCastException(result.l->clazz, returnType);
}
}
}
void XposedBridge_hookMethodNative(JNIEnv* env, jclass clazz, jobject reflectedMethodIndirect,
jobject declaredClassIndirect, jint slot, jobject additionalInfoIndirect) {
// Usage errors?
if (declaredClassIndirect == NULL || reflectedMethodIndirect == NULL) {
dvmThrowIllegalArgumentException("method and declaredClass must not be null");
return;
}
// Find the internal representation of the method
ClassObject* declaredClass = (ClassObject*) dvmDecodeIndirectRef(dvmThreadSelf(), declaredClassIndirect);
Method* method = dvmSlotToMethod(declaredClass, slot);
if (method == NULL) {
dvmThrowNoSuchMethodError("Could not get internal representation for method");
return;
}
if (isMethodHooked(method)) {
// already hooked
return;
}
// Save a copy of the original method and other hook info
XposedHookInfo* hookInfo = (XposedHookInfo*) calloc(1, sizeof(XposedHookInfo));
memcpy(hookInfo, method, sizeof(hookInfo->originalMethodStruct));
hookInfo->reflectedMethod = dvmDecodeIndirectRef(dvmThreadSelf(), env->NewGlobalRef(reflectedMethodIndirect));
hookInfo->additionalInfo = dvmDecodeIndirectRef(dvmThreadSelf(), env->NewGlobalRef(additionalInfoIndirect));
// Replace method with our own code
SET_METHOD_FLAG(method, ACC_NATIVE);
method->nativeFunc = &hookedMethodCallback;
method->insns = (const u2*) hookInfo;
method->registersSize = method->insSize;
method->outsSize = 0;
if (PTR_gDvmJit != NULL) {
// reset JIT cache
char currentValue = *((char*)PTR_gDvmJit + MEMBER_OFFSET_VAR(DvmJitGlobals,codeCacheFull));
if (currentValue == 0 || currentValue == 1) {
MEMBER_VAL(PTR_gDvmJit, DvmJitGlobals, codeCacheFull) = true;
} else {
ALOGE("Unexpected current value for codeCacheFull: %d", currentValue);
}
}
}
/**
* Simplified copy of Method.invokeNative(), but calls the original (non-hooked) method
* and has no access checks. Used to call the real implementation of hooked methods.
*/
void XposedBridge_invokeOriginalMethodNative(const u4* args, JValue* pResult,
const Method* method, ::Thread* self) {
Method* meth = (Method*) args[1];
if (meth == NULL) {
meth = dvmGetMethodFromReflectObj((Object*) args[0]);
if (isMethodHooked(meth)) {
meth = (Method*) meth->insns;
}
}
ArrayObject* params = (ArrayObject*) args[2];
ClassObject* returnType = (ClassObject*) args[3];
Object* thisObject = (Object*) args[4]; // null for static methods
ArrayObject* argList = (ArrayObject*) args[5];
// invoke the method
pResult->l = dvmInvokeMethod(thisObject, meth, argList, params, returnType, true);
return;
}
void XposedBridge_setObjectClassNative(JNIEnv* env, jclass clazz, jobject objIndirect, jclass clzIndirect) {
Object* obj = (Object*) dvmDecodeIndirectRef(dvmThreadSelf(), objIndirect);
ClassObject* clz = (ClassObject*) dvmDecodeIndirectRef(dvmThreadSelf(), clzIndirect);
if (clz->status < CLASS_INITIALIZED && !dvmInitClass(clz)) {
ALOGE("Could not initialize class %s", clz->descriptor);
return;
}
obj->clazz = clz;
}
void XposedBridge_dumpObjectNative(JNIEnv* env, jclass clazz, jobject objIndirect) {
Object* obj = (Object*) dvmDecodeIndirectRef(dvmThreadSelf(), objIndirect);
dvmDumpObject(obj);
}
jobject XposedBridge_cloneToSubclassNative(JNIEnv* env, jclass clazz, jobject objIndirect, jclass clzIndirect) {
Object* obj = (Object*) dvmDecodeIndirectRef(dvmThreadSelf(), objIndirect);
ClassObject* clz = (ClassObject*) dvmDecodeIndirectRef(dvmThreadSelf(), clzIndirect);
jobject copyIndirect = env->AllocObject(clzIndirect);
if (copyIndirect == NULL)
return NULL;
Object* copy = (Object*) dvmDecodeIndirectRef(dvmThreadSelf(), copyIndirect);
size_t size = obj->clazz->objectSize;
size_t offset = sizeof(Object);
memcpy((char*)copy + offset, (char*)obj + offset, size - offset);
if (IS_CLASS_FLAG_SET(clz, CLASS_ISFINALIZABLE))
dvmSetFinalizable(copy);
return copyIndirect;
}
void XposedBridge_removeFinalFlagNative(JNIEnv* env, jclass, jclass javaClazz) {
ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(dvmThreadSelf(), javaClazz);
if (dvmIsFinalClass(clazz)) {
clazz->accessFlags &= ~ACC_FINAL;
}
}
jint XposedBridge_getRuntime(JNIEnv* env, jclass clazz) {
return 1; // RUNTIME_DALVIK
}
} // namespace android
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。