Fix deopt method since Android 13
This commit is contained in:
parent
7a9b966ec7
commit
dcd29b8751
|
|
@ -8,6 +8,7 @@ namespace yahfa {
|
||||||
constexpr uint32_t kAccPrivate = 0x0002; // field, method, ic
|
constexpr uint32_t kAccPrivate = 0x0002; // field, method, ic
|
||||||
constexpr uint32_t kAccProtected = 0x0004; // field, method, ic
|
constexpr uint32_t kAccProtected = 0x0004; // field, method, ic
|
||||||
constexpr uint32_t kAccStatic = 0x0008; // field, method, ic
|
constexpr uint32_t kAccStatic = 0x0008; // field, method, ic
|
||||||
|
constexpr uint32_t kAccNative = 0x0100; // method
|
||||||
|
|
||||||
void init(JNIEnv *env, jclass clazz, jint sdkVersion);
|
void init(JNIEnv *env, jclass clazz, jint sdkVersion);
|
||||||
|
|
||||||
|
|
@ -24,6 +25,10 @@ namespace yahfa {
|
||||||
uint32_t getAccessFlags(void* art_method);
|
uint32_t getAccessFlags(void* art_method);
|
||||||
|
|
||||||
void setAccessFlags(void* art_method, uint32_t access_flags);
|
void setAccessFlags(void* art_method, uint32_t access_flags);
|
||||||
|
|
||||||
|
void* getEntryPoint(void* art_method);
|
||||||
|
|
||||||
|
void setEntryPoint(void* art_method, void* entry_point);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // HOOK_MAIN_H
|
#endif // HOOK_MAIN_H
|
||||||
|
|
|
||||||
|
|
@ -4,14 +4,11 @@
|
||||||
|
|
||||||
#ifndef YAHFA_TAMPOLINE_H
|
#ifndef YAHFA_TAMPOLINE_H
|
||||||
#define YAHFA_TAMPOLINE_H
|
#define YAHFA_TAMPOLINE_H
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
extern size_t OFFSET_entry_point_from_quick_compiled_code_in_ArtMethod;
|
|
||||||
|
|
||||||
void setupTrampoline();
|
namespace yahfa {
|
||||||
void *genTrampoline(void *hookMethod);
|
void setupTrampoline();
|
||||||
#ifdef __cplusplus
|
|
||||||
|
void *genTrampoline(void *hookMethod);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
#endif //YAHFA_TAMPOLINE_H
|
#endif //YAHFA_TAMPOLINE_H
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,11 @@
|
||||||
#include "trampoline.h"
|
#include "trampoline.h"
|
||||||
#include "HookMain.h"
|
#include "HookMain.h"
|
||||||
|
|
||||||
int SDKVersion;
|
|
||||||
size_t OFFSET_entry_point_from_quick_compiled_code_in_ArtMethod;
|
|
||||||
|
|
||||||
namespace yahfa {
|
namespace yahfa {
|
||||||
|
size_t OFFSET_entry_point_from_quick_compiled_code_in_ArtMethod;
|
||||||
|
int SDKVersion;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
constexpr size_t OFFSET_access_flags_in_ArtMethod = 4;
|
constexpr size_t OFFSET_access_flags_in_ArtMethod = 4;
|
||||||
constexpr uint32_t kAccCompileDontBother = 0x02000000;
|
constexpr uint32_t kAccCompileDontBother = 0x02000000;
|
||||||
|
|
@ -81,14 +82,11 @@ namespace yahfa {
|
||||||
// replace entry point
|
// replace entry point
|
||||||
void *newEntrypoint = genTrampoline(hookMethod);
|
void *newEntrypoint = genTrampoline(hookMethod);
|
||||||
LOGI("origin ep is %p, new ep is %p",
|
LOGI("origin ep is %p, new ep is %p",
|
||||||
readAddr((char *) targetMethod +
|
getEntryPoint(targetMethod),
|
||||||
OFFSET_entry_point_from_quick_compiled_code_in_ArtMethod),
|
|
||||||
newEntrypoint
|
newEntrypoint
|
||||||
);
|
);
|
||||||
if (newEntrypoint) {
|
if (newEntrypoint) {
|
||||||
writeAddr((char *) targetMethod +
|
setEntryPoint(targetMethod, newEntrypoint);
|
||||||
OFFSET_entry_point_from_quick_compiled_code_in_ArtMethod,
|
|
||||||
newEntrypoint);
|
|
||||||
} else {
|
} else {
|
||||||
LOGE("failed to allocate space for trampoline of target method");
|
LOGE("failed to allocate space for trampoline of target method");
|
||||||
return 1;
|
return 1;
|
||||||
|
|
@ -159,6 +157,16 @@ namespace yahfa {
|
||||||
write32((char *) art_method + OFFSET_access_flags_in_ArtMethod, access_flags);
|
write32((char *) art_method + OFFSET_access_flags_in_ArtMethod, access_flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *getEntryPoint(void *art_method) {
|
||||||
|
return readAddr(
|
||||||
|
(char *) art_method + OFFSET_entry_point_from_quick_compiled_code_in_ArtMethod);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setEntryPoint(void *art_method, void *entry_point) {
|
||||||
|
writeAddr((char *) art_method + OFFSET_entry_point_from_quick_compiled_code_in_ArtMethod,
|
||||||
|
entry_point);
|
||||||
|
}
|
||||||
|
|
||||||
jobject findMethodNative(JNIEnv *env, [[maybe_unused]] jclass clazz,
|
jobject findMethodNative(JNIEnv *env, [[maybe_unused]] jclass clazz,
|
||||||
jclass targetClass,
|
jclass targetClass,
|
||||||
jstring methodName,
|
jstring methodName,
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,12 @@
|
||||||
// Created by liuruikai756 on 05/07/2017.
|
// Created by liuruikai756 on 05/07/2017.
|
||||||
//
|
//
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <string.h>
|
#include <cstring>
|
||||||
#include <errno.h>
|
#include <cerrno>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <stdio.h>
|
#include <cstdio>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <stdlib.h>
|
#include <cstdlib>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
|
@ -19,13 +19,16 @@
|
||||||
|
|
||||||
static_assert(std::endian::native == std::endian::little, "Unsupported architecture");
|
static_assert(std::endian::native == std::endian::little, "Unsupported architecture");
|
||||||
|
|
||||||
union Trampoline {
|
namespace yahfa {
|
||||||
uintptr_t addr;
|
extern size_t OFFSET_entry_point_from_quick_compiled_code_in_ArtMethod;
|
||||||
unsigned count : 12;
|
|
||||||
};
|
|
||||||
|
|
||||||
static_assert(sizeof(Trampoline) == sizeof(uintptr_t), "Unsupported architecture");
|
union Trampoline {
|
||||||
static_assert(std::atomic_uintptr_t ::is_always_lock_free, "Unsupported architecture");
|
uintptr_t addr;
|
||||||
|
unsigned count: 12;
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(Trampoline) == sizeof(uintptr_t), "Unsupported architecture");
|
||||||
|
static_assert(std::atomic_uintptr_t::is_always_lock_free, "Unsupported architecture");
|
||||||
|
|
||||||
// trampoline:
|
// trampoline:
|
||||||
// 1. set eax/r0/x0 to the hook ArtMethod addr
|
// 1. set eax/r0/x0 to the hook ArtMethod addr
|
||||||
|
|
@ -34,110 +37,111 @@ static_assert(std::atomic_uintptr_t ::is_always_lock_free, "Unsupported architec
|
||||||
// b8 78 56 34 12 ; mov eax, 0x12345678 (addr of the hook method)
|
// b8 78 56 34 12 ; mov eax, 0x12345678 (addr of the hook method)
|
||||||
// ff 70 20 ; push DWORD PTR [eax + 0x20]
|
// ff 70 20 ; push DWORD PTR [eax + 0x20]
|
||||||
// c3 ; ret
|
// c3 ; ret
|
||||||
unsigned char trampoline[] = "\xb8\x78\x56\x34\x12\xff\x70\x20\xc3";
|
unsigned char trampoline[] = "\xb8\x78\x56\x34\x12\xff\x70\x20\xc3";
|
||||||
#elif defined(__x86_64__)
|
#elif defined(__x86_64__)
|
||||||
// 48 bf 78 56 34 12 78 56 34 12 ; movabs rdi, 0x1234567812345678
|
// 48 bf 78 56 34 12 78 56 34 12 ; movabs rdi, 0x1234567812345678
|
||||||
// ff 77 20 ; push QWORD PTR [rdi + 0x20]
|
// ff 77 20 ; push QWORD PTR [rdi + 0x20]
|
||||||
// c3 ; ret
|
// c3 ; ret
|
||||||
unsigned char trampoline[] = "\x48\xbf\x78\x56\x34\x12\x78\x56\x34\x12\xff\x77\x20\xc3";
|
unsigned char trampoline[] = "\x48\xbf\x78\x56\x34\x12\x78\x56\x34\x12\xff\x77\x20\xc3";
|
||||||
|
|
||||||
#elif defined(__arm__)
|
#elif defined(__arm__)
|
||||||
// 00 00 9F E5 ; ldr r0, [pc, #0]
|
// 00 00 9F E5 ; ldr r0, [pc, #0]
|
||||||
// 20 F0 90 E5 ; ldr pc, [r0, 0x20]
|
// 20 F0 90 E5 ; ldr pc, [r0, 0x20]
|
||||||
// 78 56 34 12 ; 0x12345678 (addr of the hook method)
|
// 78 56 34 12 ; 0x12345678 (addr of the hook method)
|
||||||
unsigned char trampoline[] = "\x00\x00\x9f\xe5\x20\xf0\x90\xe5\x78\x56\x34\x12";
|
unsigned char trampoline[] = "\x00\x00\x9f\xe5\x20\xf0\x90\xe5\x78\x56\x34\x12";
|
||||||
|
|
||||||
#elif defined(__aarch64__)
|
#elif defined(__aarch64__)
|
||||||
// 60 00 00 58 ; ldr x0, 12
|
// 60 00 00 58 ; ldr x0, 12
|
||||||
// 10 00 40 F8 ; ldr x16, [x0, #0x00]
|
// 10 00 40 F8 ; ldr x16, [x0, #0x00]
|
||||||
// 00 02 1f d6 ; br x16
|
// 00 02 1f d6 ; br x16
|
||||||
// 78 56 34 12
|
// 78 56 34 12
|
||||||
// 78 56 34 12 ; 0x1234567812345678 (addr of the hook method)
|
// 78 56 34 12 ; 0x1234567812345678 (addr of the hook method)
|
||||||
unsigned char trampoline[] = "\x60\x00\x00\x58\x10\x00\x40\xf8\x00\x02\x1f\xd6\x78\x56\x34\x12\x78\x56\x34\x12";
|
unsigned char trampoline[] = "\x60\x00\x00\x58\x10\x00\x40\xf8\x00\x02\x1f\xd6\x78\x56\x34\x12\x78\x56\x34\x12";
|
||||||
#endif
|
#endif
|
||||||
static std::atomic_uintptr_t trampoline_pool{0};
|
static std::atomic_uintptr_t trampoline_pool{0};
|
||||||
static std::atomic_flag trampoline_lock{false};
|
static std::atomic_flag trampoline_lock{false};
|
||||||
static constexpr size_t trampolineSize = roundUpToPtrSize(sizeof(trampoline));
|
static constexpr size_t trampolineSize = roundUpToPtrSize(sizeof(trampoline));
|
||||||
static constexpr size_t pageSize = 4096;
|
static constexpr size_t pageSize = 4096;
|
||||||
static constexpr size_t trampolineNumPerPage = pageSize / trampolineSize;
|
static constexpr size_t trampolineNumPerPage = pageSize / trampolineSize;
|
||||||
|
|
||||||
static inline void FlushCache(void *addr, size_t size) {
|
static inline void FlushCache(void *addr, size_t size) {
|
||||||
__builtin___clear_cache((char *) addr, (char *) ((uintptr_t) addr + size));
|
__builtin___clear_cache((char *) addr, (char *) ((uintptr_t) addr + size));
|
||||||
}
|
}
|
||||||
|
|
||||||
void *genTrampoline(void *hookMethod) {
|
void *genTrampoline(void *hookMethod) {
|
||||||
unsigned count;
|
unsigned count;
|
||||||
uintptr_t addr;
|
uintptr_t addr;
|
||||||
while (true) {
|
while (true) {
|
||||||
auto tl = Trampoline {.addr = trampoline_pool.fetch_add(1, std::memory_order_release)};
|
auto tl = Trampoline{.addr = trampoline_pool.fetch_add(1, std::memory_order_release)};
|
||||||
count = tl.count;
|
count = tl.count;
|
||||||
addr = tl.addr & ~uintptr_t(0xfff);
|
addr = tl.addr & ~uintptr_t(0xfff);
|
||||||
if (addr == 0 || count >= trampolineNumPerPage) {
|
if (addr == 0 || count >= trampolineNumPerPage) {
|
||||||
if (trampoline_lock.test_and_set(std::memory_order_acq_rel)) {
|
if (trampoline_lock.test_and_set(std::memory_order_acq_rel)) {
|
||||||
trampoline_lock.wait(true, std::memory_order_acquire);
|
trampoline_lock.wait(true, std::memory_order_acquire);
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
addr = reinterpret_cast<uintptr_t>(mmap(nullptr, pageSize,
|
addr = reinterpret_cast<uintptr_t>(mmap(nullptr, pageSize,
|
||||||
PROT_READ | PROT_WRITE | PROT_EXEC,
|
PROT_READ | PROT_WRITE | PROT_EXEC,
|
||||||
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0));
|
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0));
|
||||||
if (addr == reinterpret_cast<uintptr_t>(MAP_FAILED)) {
|
if (addr == reinterpret_cast<uintptr_t>(MAP_FAILED)) {
|
||||||
LOGE("mmap failed, errno = %s", strerror(errno));
|
LOGE("mmap failed, errno = %s", strerror(errno));
|
||||||
|
trampoline_lock.clear(std::memory_order_release);
|
||||||
|
trampoline_lock.notify_all();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
count = 0;
|
||||||
|
tl.addr = addr;
|
||||||
|
tl.count = count + 1;
|
||||||
|
trampoline_pool.store(tl.addr, std::memory_order_release);
|
||||||
trampoline_lock.clear(std::memory_order_release);
|
trampoline_lock.clear(std::memory_order_release);
|
||||||
trampoline_lock.notify_all();
|
trampoline_lock.notify_all();
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
count = 0;
|
|
||||||
tl.addr = addr;
|
|
||||||
tl.count = count + 1;
|
|
||||||
trampoline_pool.store(tl.addr, std::memory_order_release);
|
|
||||||
trampoline_lock.clear(std::memory_order_release);
|
|
||||||
trampoline_lock.notify_all();
|
|
||||||
}
|
}
|
||||||
|
LOGI("trampoline: count = %u, addr = %zx, target = %zx", count, addr,
|
||||||
|
addr + count * trampolineSize);
|
||||||
|
addr = addr + count * trampolineSize;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
LOGI("trampoline: count = %u, addr = %zx, target = %zx", count, addr, addr + count * trampolineSize);
|
unsigned char *targetAddr = reinterpret_cast<unsigned char *>(addr);
|
||||||
addr = addr + count * trampolineSize;
|
memcpy(targetAddr, trampoline,
|
||||||
break;
|
sizeof(trampoline)); // do not use trampolineSize since it's a rounded size
|
||||||
|
|
||||||
|
// replace with the actual ArtMethod addr
|
||||||
|
#if defined(__i386__)
|
||||||
|
memcpy(targetAddr + 1, &hookMethod, pointer_size);
|
||||||
|
|
||||||
|
#elif defined(__x86_64__)
|
||||||
|
memcpy((char*)targetAddr + 2, &hookMethod, pointer_size);
|
||||||
|
|
||||||
|
#elif defined(__arm__)
|
||||||
|
memcpy(targetAddr+8, &hookMethod, pointer_size);
|
||||||
|
|
||||||
|
#elif defined(__aarch64__)
|
||||||
|
memcpy(targetAddr + 12, &hookMethod, pointer_size);
|
||||||
|
|
||||||
|
#else
|
||||||
|
#error Unsupported architecture
|
||||||
|
#endif
|
||||||
|
FlushCache(targetAddr, sizeof(trampoline));
|
||||||
|
|
||||||
|
return targetAddr;
|
||||||
}
|
}
|
||||||
unsigned char *targetAddr = reinterpret_cast<unsigned char *>(addr);
|
|
||||||
// unsigned char*targetAddr = reinterpret_cast<unsigned char*>(mmap(NULL, trampolineSize, PROT_READ | PROT_WRITE | PROT_EXEC,
|
|
||||||
// MAP_ANONYMOUS | MAP_PRIVATE, -1, 0));
|
|
||||||
memcpy(targetAddr, trampoline,
|
|
||||||
sizeof(trampoline)); // do not use trampolineSize since it's a rounded size
|
|
||||||
|
|
||||||
// replace with the actual ArtMethod addr
|
void setupTrampoline() {
|
||||||
#if defined(__i386__)
|
#if defined(__i386__)
|
||||||
memcpy(targetAddr+1, &hookMethod, pointer_size);
|
trampoline[7] = (unsigned char) OFFSET_entry_point_from_quick_compiled_code_in_ArtMethod;
|
||||||
|
|
||||||
#elif defined(__x86_64__)
|
#elif defined(__x86_64__)
|
||||||
memcpy((char*)targetAddr + 2, &hookMethod, pointer_size);
|
trampoline[12] = (unsigned char)OFFSET_entry_point_from_quick_compiled_code_in_ArtMethod;
|
||||||
|
|
||||||
#elif defined(__arm__)
|
#elif defined(__arm__)
|
||||||
memcpy(targetAddr+8, &hookMethod, pointer_size);
|
trampoline[4] = (unsigned char)OFFSET_entry_point_from_quick_compiled_code_in_ArtMethod;
|
||||||
|
|
||||||
#elif defined(__aarch64__)
|
#elif defined(__aarch64__)
|
||||||
memcpy(targetAddr + 12, &hookMethod, pointer_size);
|
trampoline[5] |=
|
||||||
|
((unsigned char) OFFSET_entry_point_from_quick_compiled_code_in_ArtMethod) << 4;
|
||||||
|
trampoline[6] |=
|
||||||
|
((unsigned char) OFFSET_entry_point_from_quick_compiled_code_in_ArtMethod) >> 4;
|
||||||
#else
|
#else
|
||||||
#error Unsupported architecture
|
#error Unsupported architecture
|
||||||
#endif
|
#endif
|
||||||
FlushCache(targetAddr, sizeof(trampoline));
|
}
|
||||||
|
|
||||||
return targetAddr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setupTrampoline() {
|
|
||||||
#if defined(__i386__)
|
|
||||||
trampoline[7] = (unsigned char)OFFSET_entry_point_from_quick_compiled_code_in_ArtMethod;
|
|
||||||
#elif defined(__x86_64__)
|
|
||||||
trampoline[12] = (unsigned char)OFFSET_entry_point_from_quick_compiled_code_in_ArtMethod;
|
|
||||||
#elif defined(__arm__)
|
|
||||||
trampoline[4] = (unsigned char)OFFSET_entry_point_from_quick_compiled_code_in_ArtMethod;
|
|
||||||
#elif defined(__aarch64__)
|
|
||||||
trampoline[5] |=
|
|
||||||
((unsigned char) OFFSET_entry_point_from_quick_compiled_code_in_ArtMethod) << 4;
|
|
||||||
trampoline[6] |=
|
|
||||||
((unsigned char) OFFSET_entry_point_from_quick_compiled_code_in_ArtMethod) >> 4;
|
|
||||||
#else
|
|
||||||
#error Unsupported architecture
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -101,6 +101,9 @@ namespace art {
|
||||||
return backup(art_method, quick_code);
|
return backup(art_method, quick_code);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
CREATE_FUNC_SYMBOL_ENTRY(void, art_quick_to_interpreter_bridge, void*) {}
|
||||||
|
CREATE_FUNC_SYMBOL_ENTRY(void, art_quick_generic_jni_trampoline, void*) {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ClassLinker(void *thiz) : HookedObject(thiz) {}
|
ClassLinker(void *thiz) : HookedObject(thiz) {}
|
||||||
|
|
||||||
|
|
@ -117,7 +120,9 @@ namespace art {
|
||||||
RETRIEVE_MEM_FUNC_SYMBOL(SetEntryPointsToInterpreter,
|
RETRIEVE_MEM_FUNC_SYMBOL(SetEntryPointsToInterpreter,
|
||||||
"_ZNK3art11ClassLinker27SetEntryPointsToInterpreterEPNS_9ArtMethodE");
|
"_ZNK3art11ClassLinker27SetEntryPointsToInterpreterEPNS_9ArtMethodE");
|
||||||
|
|
||||||
lspd::HookSyms(handle, ShouldUseInterpreterEntrypoint);
|
if (api_level < __ANDROID_API_T__) {
|
||||||
|
lspd::HookSyms(handle, ShouldUseInterpreterEntrypoint);
|
||||||
|
}
|
||||||
|
|
||||||
if (api_level >= __ANDROID_API_R__) {
|
if (api_level >= __ANDROID_API_R__) {
|
||||||
// In android R, FixupStaticTrampolines won't be called unless it's marking it as
|
// In android R, FixupStaticTrampolines won't be called unless it's marking it as
|
||||||
|
|
@ -139,6 +144,11 @@ namespace art {
|
||||||
// "_ZN3art11ClassLinker40MakeInitializedClassesVisiblyInitializedEPNS_6ThreadEb");
|
// "_ZN3art11ClassLinker40MakeInitializedClassesVisiblyInitializedEPNS_6ThreadEb");
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
RETRIEVE_FUNC_SYMBOL(art_quick_to_interpreter_bridge, "art_quick_to_interpreter_bridge");
|
||||||
|
RETRIEVE_FUNC_SYMBOL(art_quick_generic_jni_trampoline, "art_quick_generic_jni_trampoline");
|
||||||
|
|
||||||
|
LOGD("art_quick_to_interpreter_bridge = %p", art_quick_to_interpreter_bridgeSym);
|
||||||
|
LOGD("art_quick_generic_jni_trampoline = %p", art_quick_generic_jni_trampolineSym);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[gnu::always_inline]]
|
[[gnu::always_inline]]
|
||||||
|
|
@ -151,6 +161,15 @@ namespace art {
|
||||||
|
|
||||||
[[gnu::always_inline]]
|
[[gnu::always_inline]]
|
||||||
void SetEntryPointsToInterpreter(void *art_method) const {
|
void SetEntryPointsToInterpreter(void *art_method) const {
|
||||||
|
if (art_quick_to_interpreter_bridgeSym && art_quick_generic_jni_trampolineSym) [[likely]] {
|
||||||
|
if (yahfa::getAccessFlags(art_method) & yahfa::kAccNative) [[unlikely]] {
|
||||||
|
yahfa::setEntryPoint(art_method,
|
||||||
|
reinterpret_cast<void *>(art_quick_generic_jni_trampolineSym));
|
||||||
|
} else {
|
||||||
|
yahfa::setEntryPoint(art_method,
|
||||||
|
reinterpret_cast<void *>(art_quick_to_interpreter_bridgeSym));
|
||||||
|
}
|
||||||
|
}
|
||||||
SetEntryPointsToInterpreter(thiz_, art_method);
|
SetEntryPointsToInterpreter(thiz_, art_method);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue