Refine codes

This commit is contained in:
LoveSy 2022-03-12 16:10:55 +08:00
parent 6d40254a3f
commit b95af07672
11 changed files with 65 additions and 198 deletions

View File

@ -1,101 +0,0 @@
#pragma once
#include "art/thread.hpp"
#include "common.hpp"
namespace lsplant::art {
namespace dex {
class ClassDef {};
} // namespace dex
namespace mirror {
class Class {
private:
CREATE_MEM_FUNC_SYMBOL_ENTRY(const char *, GetDescriptor, Class *thiz, std::string *storage) {
if (GetDescriptorSym) [[likely]]
return GetDescriptor(thiz, storage);
else
return "";
}
CREATE_MEM_FUNC_SYMBOL_ENTRY(const dex::ClassDef *, GetClassDef, Class *thiz) {
if (GetClassDefSym) [[likely]]
return GetClassDefSym(thiz);
return nullptr;
}
public:
static bool Init(JNIEnv *env, const HookHandler &handler) {
if (!RETRIEVE_MEM_FUNC_SYMBOL(GetDescriptor,
"_ZN3art6mirror5Class13GetDescriptorEPNSt3__112"
"basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE")) {
return false;
}
if (!RETRIEVE_MEM_FUNC_SYMBOL(GetClassDef, "_ZN3art6mirror5Class11GetClassDefEv")) {
return false;
}
auto clazz = JNI_FindClass(env, "java/lang/Class");
if (!clazz) {
LOGE("Failed to find Class");
return false;
}
if (class_status = JNI_GetFieldID(env, clazz, "status", "I"); !class_status) {
LOGE("Failed to find status");
return false;
}
int sdk_int = GetAndroidApiLevel();
if (sdk_int >= __ANDROID_API_P__) {
initialized_status = -14;
} else if (sdk_int == __ANDROID_API_O_MR1__) {
initialized_status = 11;
} else {
initialized_status = 10;
}
return true;
}
const char *GetDescriptor(std::string *storage) {
if (GetDescriptorSym) {
return GetDescriptor(storage);
}
return "";
}
std::string GetDescriptor() {
std::string storage;
return GetDescriptor(&storage);
}
const dex::ClassDef *GetClassDef() {
if (GetClassDefSym) return GetClassDef(this);
return nullptr;
}
static int GetStatus(JNIEnv *env, jclass clazz) {
int status = JNI_GetIntField(env, clazz, class_status);
return initialized_status < 0 ? static_cast<uint32_t>(status) >> (32 - 4) : status;
}
static bool IsInitialized(JNIEnv *env, jclass clazz) {
return initialized_status < 0 ? GetStatus(env, clazz) >= -initialized_status
: GetStatus(env, clazz) == initialized_status;
}
static Class *FromReflectedClass(JNIEnv *, jclass clazz) {
return reinterpret_cast<Class *>(art::Thread::Current()->DecodeJObject(clazz));
}
private:
inline static jfieldID class_status = nullptr;
inline static int initialized_status = 0;
};
} // namespace mirror
} // namespace lsplant::art

View File

@ -1,6 +1,5 @@
#pragma once #pragma once
#include "art/mirror/class.hpp"
#include "common.hpp" #include "common.hpp"
namespace lsplant::art { namespace lsplant::art {

View File

@ -1,6 +1,5 @@
#pragma once #pragma once
#include "art/mirror/class.hpp"
#include "art/runtime/art_method.hpp" #include "art/runtime/art_method.hpp"
#include "art/thread.hpp" #include "art/thread.hpp"
#include "common.hpp" #include "common.hpp"
@ -40,7 +39,7 @@ public:
static bool Init(const HookHandler &handler) { static bool Init(const HookHandler &handler) {
int sdk_int = GetAndroidApiLevel(); int sdk_int = GetAndroidApiLevel();
if (sdk_int >= __ANDROID_API_N__) { if (sdk_int >= __ANDROID_API_N__) [[likely]] {
if (!HookSyms(handler, ShouldUseInterpreterEntrypoint, ShouldStayInSwitchInterpreter)) if (!HookSyms(handler, ShouldUseInterpreterEntrypoint, ShouldStayInSwitchInterpreter))
[[unlikely]] { [[unlikely]] {
return false; return false;
@ -49,13 +48,14 @@ public:
if (!RETRIEVE_MEM_FUNC_SYMBOL( if (!RETRIEVE_MEM_FUNC_SYMBOL(
SetEntryPointsToInterpreter, SetEntryPointsToInterpreter,
"_ZNK3art11ClassLinker27SetEntryPointsToInterpreterEPNS_9ArtMethodE")) { "_ZNK3art11ClassLinker27SetEntryPointsToInterpreterEPNS_9ArtMethodE"))
[[unlikely]] {
if (!RETRIEVE_FUNC_SYMBOL(art_quick_to_interpreter_bridge, if (!RETRIEVE_FUNC_SYMBOL(art_quick_to_interpreter_bridge,
"art_quick_to_interpreter_bridge")) { "art_quick_to_interpreter_bridge")) [[unlikely]] {
return false; return false;
} }
if (!RETRIEVE_FUNC_SYMBOL(art_quick_generic_jni_trampoline, if (!RETRIEVE_FUNC_SYMBOL(art_quick_generic_jni_trampoline,
"art_quick_generic_jni_trampoline")) { "art_quick_generic_jni_trampoline")) [[unlikely]] {
return false; return false;
} }
LOGD("art_quick_to_interpreter_bridge = %p", art_quick_to_interpreter_bridgeSym); LOGD("art_quick_to_interpreter_bridge = %p", art_quick_to_interpreter_bridgeSym);

View File

@ -45,11 +45,6 @@ class DexFile {
return nullptr; return nullptr;
} }
CREATE_MEM_FUNC_SYMBOL_ENTRY(void, push_back, std::vector<const DexFile*>* thiz,
const DexFile** dex_file) {
push_backSym(thiz, dex_file);
}
public: public:
static const DexFile* OpenMemory(const void* dex_file, size_t size, std::string location, static const DexFile* OpenMemory(const void* dex_file, size_t size, std::string location,
std::string* error_msg) { std::string* error_msg) {
@ -58,11 +53,11 @@ public:
reinterpret_cast<const Header*>(dex_file)->checksum_, nullptr, reinterpret_cast<const Header*>(dex_file)->checksum_, nullptr,
nullptr, error_msg) nullptr, error_msg)
.release(); .release();
} else if (OpenMemoryRawSym) { } else if (OpenMemoryRawSym) [[likely]] {
return OpenMemoryRaw(reinterpret_cast<const uint8_t*>(dex_file), size, location, return OpenMemoryRaw(reinterpret_cast<const uint8_t*>(dex_file), size, location,
reinterpret_cast<const Header*>(dex_file)->checksum_, nullptr, reinterpret_cast<const Header*>(dex_file)->checksum_, nullptr,
nullptr, error_msg); nullptr, error_msg);
} else if (OpenMemoryWithoutOdexSym) { } else if (OpenMemoryWithoutOdexSym) [[likely]] {
return OpenMemoryWithoutOdex(reinterpret_cast<const uint8_t*>(dex_file), size, location, return OpenMemoryWithoutOdex(reinterpret_cast<const uint8_t*>(dex_file), size, location,
reinterpret_cast<const Header*>(dex_file)->checksum_, reinterpret_cast<const Header*>(dex_file)->checksum_,
nullptr, error_msg); nullptr, error_msg);
@ -119,26 +114,26 @@ public:
return false; return false;
} }
dex_file_class = JNI_NewGlobalRef(env, JNI_FindClass(env, "dalvik/system/DexFile")); dex_file_class = JNI_NewGlobalRef(env, JNI_FindClass(env, "dalvik/system/DexFile"));
if (!dex_file_class) { if (!dex_file_class) [[unlikely]] {
return false; return false;
} }
if (sdk_int >= __ANDROID_API_M__) { if (sdk_int >= __ANDROID_API_M__) [[unlikely]] {
cookie_field = JNI_GetFieldID(env, dex_file_class, "mCookie", "Ljava/lang/Object;"); cookie_field = JNI_GetFieldID(env, dex_file_class, "mCookie", "Ljava/lang/Object;");
} else { } else {
cookie_field = JNI_GetFieldID(env, dex_file_class, "mCookie", "J"); cookie_field = JNI_GetFieldID(env, dex_file_class, "mCookie", "J");
dex_file_start_index = -1; dex_file_start_index = -1;
} }
if (!cookie_field) { if (!cookie_field) [[unlikely]] {
return false; return false;
} }
file_name_field = JNI_GetFieldID(env, dex_file_class, "mFileName", "Ljava/lang/String;"); file_name_field = JNI_GetFieldID(env, dex_file_class, "mFileName", "Ljava/lang/String;");
if (!file_name_field) { if (!file_name_field) [[unlikely]] {
return false; return false;
} }
if (sdk_int >= __ANDROID_API_N__) { if (sdk_int >= __ANDROID_API_N__) [[likely]] {
internal_cookie_field = internal_cookie_field =
JNI_GetFieldID(env, dex_file_class, "mInternalCookie", "Ljava/lang/Object;"); JNI_GetFieldID(env, dex_file_class, "mInternalCookie", "Ljava/lang/Object;");
if (!internal_cookie_field) { if (!internal_cookie_field) [[unlikely]] {
return false; return false;
} }
dex_file_start_index = 1u; dex_file_start_index = 1u;

View File

@ -16,17 +16,13 @@ private:
class ScopedGCCriticalSection { class ScopedGCCriticalSection {
CREATE_MEM_FUNC_SYMBOL_ENTRY(void, constructor, ScopedGCCriticalSection *thiz, Thread *self, CREATE_MEM_FUNC_SYMBOL_ENTRY(void, constructor, ScopedGCCriticalSection *thiz, Thread *self,
GcCause cause, CollectorType collector_type) { GcCause cause, CollectorType collector_type) {
if (thiz == nullptr) [[unlikely]] if (thiz && constructorSym) [[likely]]
return;
if (constructorSym) [[likely]]
return constructorSym(thiz, self, cause, collector_type); return constructorSym(thiz, self, cause, collector_type);
} }
CREATE_MEM_FUNC_SYMBOL_ENTRY(void, destructor, ScopedGCCriticalSection *thiz) { CREATE_MEM_FUNC_SYMBOL_ENTRY(void, destructor, ScopedGCCriticalSection *thiz) {
if (thiz == nullptr) [[unlikely]] if (thiz && destructorSym) [[likely]]
return; destructorSym(thiz);
if (destructorSym) [[likely]]
return destructorSym(thiz);
} }
public: public:
@ -39,7 +35,7 @@ public:
static bool Init(const HookHandler &handler) { static bool Init(const HookHandler &handler) {
// for Android M, it's safe to not found since we have suspendVM & resumeVM // for Android M, it's safe to not found since we have suspendVM & resumeVM
auto sdk_int = GetAndroidApiLevel(); auto sdk_int = GetAndroidApiLevel();
if (sdk_int >= __ANDROID_API_N__) { if (sdk_int >= __ANDROID_API_N__) [[likely]] {
if (!RETRIEVE_MEM_FUNC_SYMBOL(constructor, if (!RETRIEVE_MEM_FUNC_SYMBOL(constructor,
"_ZN3art2gc23ScopedGCCriticalSectionC2EPNS_6ThreadENS0_" "_ZN3art2gc23ScopedGCCriticalSectionC2EPNS_6ThreadENS0_"
"7GcCauseENS0_13CollectorTypeE")) [[unlikely]] { "7GcCauseENS0_13CollectorTypeE")) [[unlikely]] {

View File

@ -36,7 +36,7 @@ public:
} }
} }
if (sdk_int >= __ANDROID_API_N__) [[likely]] { if (sdk_int >= __ANDROID_API_N__) [[likely]] {
if (!HookSyms(handler, GarbageCollectCache)) { if (!HookSyms(handler, GarbageCollectCache)) [[unlikely]] {
return false; return false;
} }
} }

View File

@ -10,7 +10,7 @@ class Thread {
}; };
CREATE_MEM_FUNC_SYMBOL_ENTRY(ObjPtr, DecodeJObject, Thread *thiz, jobject obj) { CREATE_MEM_FUNC_SYMBOL_ENTRY(ObjPtr, DecodeJObject, Thread *thiz, jobject obj) {
if (DecodeJObjectSym) if (DecodeJObjectSym) [[likely]]
return DecodeJObjectSym(thiz, obj); return DecodeJObjectSym(thiz, obj);
else else
return {.data = nullptr}; return {.data = nullptr};
@ -27,10 +27,12 @@ public:
static Thread *Current() { return CurrentFromGdb(); } static Thread *Current() { return CurrentFromGdb(); }
static bool Init(const HookHandler &handler) { static bool Init(const HookHandler &handler) {
if (!RETRIEVE_MEM_FUNC_SYMBOL(DecodeJObject, "_ZNK3art6Thread13DecodeJObjectEP8_jobject")) { if (!RETRIEVE_MEM_FUNC_SYMBOL(DecodeJObject, "_ZNK3art6Thread13DecodeJObjectEP8_jobject"))
[[unlikely]] {
return false; return false;
} }
if (!RETRIEVE_FUNC_SYMBOL(CurrentFromGdb, "_ZN3art6Thread14CurrentFromGdbEv")) { if (!RETRIEVE_FUNC_SYMBOL(CurrentFromGdb, "_ZN3art6Thread14CurrentFromGdbEv"))
[[unlikely]] {
return false; return false;
} }
return true; return true;

View File

@ -7,9 +7,7 @@ namespace lsplant::art::thread_list {
class ScopedSuspendAll { class ScopedSuspendAll {
CREATE_MEM_FUNC_SYMBOL_ENTRY(void, constructor, ScopedSuspendAll *thiz, const char *cause, CREATE_MEM_FUNC_SYMBOL_ENTRY(void, constructor, ScopedSuspendAll *thiz, const char *cause,
bool long_suspend) { bool long_suspend) {
if (thiz == nullptr) [[unlikely]] if (thiz && constructorSym) [[likely]] {
return;
if (constructorSym) [[likely]] {
return constructorSym(thiz, cause, long_suspend); return constructorSym(thiz, cause, long_suspend);
} else { } else {
SuspendVM(); SuspendVM();
@ -17,10 +15,7 @@ class ScopedSuspendAll {
} }
CREATE_MEM_FUNC_SYMBOL_ENTRY(void, destructor, ScopedSuspendAll *thiz) { CREATE_MEM_FUNC_SYMBOL_ENTRY(void, destructor, ScopedSuspendAll *thiz) {
if (thiz == nullptr) [[unlikely]] { if (thiz && destructorSym) [[likely]] {
return;
}
if (destructorSym) [[likely]] {
return destructorSym(thiz); return destructorSym(thiz);
} else { } else {
ResumeVM(); ResumeVM();
@ -47,15 +42,13 @@ public:
~ScopedSuspendAll() { destructor(this); } ~ScopedSuspendAll() { destructor(this); }
static bool Init(const HookHandler &handler) { static bool Init(const HookHandler &handler) {
if (!RETRIEVE_MEM_FUNC_SYMBOL(constructor, "_ZN3art16ScopedSuspendAllC2EPKcb")) { if (!RETRIEVE_MEM_FUNC_SYMBOL(constructor, "_ZN3art16ScopedSuspendAllC2EPKcb") &&
if (!RETRIEVE_FUNC_SYMBOL(SuspendVM, "_ZN3art3Dbg9SuspendVMEv")) { !RETRIEVE_FUNC_SYMBOL(SuspendVM, "_ZN3art3Dbg9SuspendVMEv")) [[unlikely]] {
return false; return false;
}
} }
if (!RETRIEVE_MEM_FUNC_SYMBOL(destructor, "_ZN3art16ScopedSuspendAllD2Ev")) { if (!RETRIEVE_MEM_FUNC_SYMBOL(destructor, "_ZN3art16ScopedSuspendAllD2Ev") &&
if (!RETRIEVE_FUNC_SYMBOL(ResumeVM, "_ZN3art3Dbg8ResumeVMEv")) { !RETRIEVE_FUNC_SYMBOL(ResumeVM, "_ZN3art3Dbg8ResumeVMEv")) [[unlikely]] {
return false; return false;
}
} }
return true; return true;
} }

View File

@ -6,7 +6,6 @@
#include <shared_mutex> #include <shared_mutex>
#include <string_view> #include <string_view>
#include <unordered_map> #include <unordered_map>
#include <unordered_set>
#include "logging.hpp" #include "logging.hpp"
#include "lsplant.hpp" #include "lsplant.hpp"
@ -55,22 +54,8 @@ inline auto GetAndroidApiLevel() {
inline static constexpr auto kPointerSize = sizeof(void *); inline static constexpr auto kPointerSize = sizeof(void *);
template <typename T>
inline T GetArtSymbol(const std::function<void *(std::string_view)> &resolver,
std::string_view symbol) requires(std::is_pointer_v<T>) {
if (auto *result = resolver(symbol); result) {
return reinterpret_cast<T>(result);
} else {
LOGW("Failed to find symbol %*s", static_cast<int>(symbol.length()), symbol.data());
return nullptr;
}
}
namespace art { namespace art {
class ArtMethod; class ArtMethod;
namespace dex {
class ClassDef;
}
} // namespace art } // namespace art
namespace { namespace {
@ -92,7 +77,7 @@ inline std::list<std::pair<art::ArtMethod *, art::ArtMethod *>> GetJitMovements(
return std::move(jit_movements_); return std::move(jit_movements_);
} }
inline void RecordHooked(art::ArtMethod *target, jobject reflected_backup, art::ArtMethod* backup) { inline void RecordHooked(art::ArtMethod *target, jobject reflected_backup, art::ArtMethod *backup) {
std::unique_lock lk(hooked_methods_lock_); std::unique_lock lk(hooked_methods_lock_);
hooked_methods_.emplace(target, std::make_pair(reflected_backup, backup)); hooked_methods_.emplace(target, std::make_pair(reflected_backup, backup));
} }

View File

@ -59,8 +59,8 @@ struct InitInfo {
/// \return Indicate whether initialization succeed. Behavior is undefined if calling other /// \return Indicate whether initialization succeed. Behavior is undefined if calling other
/// LSPlant interfaces before initialization or after a fail initialization. /// LSPlant interfaces before initialization or after a fail initialization.
/// \see InitInfo. /// \see InitInfo.
[[nodiscard]] [[maybe_unused]] [[gnu::visibility("default")]] bool Init(JNIEnv *env, [[nodiscard, maybe_unused, gnu::visibility("default")]] bool Init(JNIEnv *env,
const InitInfo &info); const InitInfo &info);
/// \brief Hook a Java method by providing the \p target_method together with the context object /// \brief Hook a Java method by providing the \p target_method together with the context object
/// \p hooker_object and its callback \p callback_method. /// \p hooker_object and its callback \p callback_method.
@ -75,29 +75,32 @@ struct InitInfo {
/// \param[in] callback_method The callback method to the \p hooker_object is used to replace the /// \param[in] callback_method The callback method to the \p hooker_object is used to replace the
/// \p target_method. Whenever the \p target_method is invoked, the \p callback_method will be /// \p target_method. Whenever the \p target_method is invoked, the \p callback_method will be
/// invoked instead of the original \p target_method. The signature of the \p callback_method must /// invoked instead of the original \p target_method. The signature of the \p callback_method must
/// be:<br> /// be:
/// \code{.java} /// \code{.java}
/// public Object callback_method(Object []args) /// public Object callback_method(Object []args)
/// \endcode<br> /// \endcode
/// That is, the return type must be \p Object and the parameter type must be \b Object[]. Behavior /// That is, the return type must be \p Object and the parameter type must be \b Object[]. Behavior
/// is undefined if the signature does not match the requirement. /// is undefined if the signature does not match the requirement.
/// args[0] is the this object for non-static methods and there is NOT null this object placeholder
/// for static methods.
/// Extra info can be provided by defining member variables of \p hooker_object. /// Extra info can be provided by defining member variables of \p hooker_object.
/// This method must be a method to \p hooker_object. /// This method must be a method to \p hooker_object.
/// \return The backup method. You can invoke it by reflection to invoke the original method. null /// \return The backup method. You can invoke it
/// if fails. /// by reflection to invoke the original method. null if fails.
/// \note This function will automatically generate a stub class for hook. To help debug, you /// \note This function will
/// can set the generated class name, its field name, its source name and its method name /// automatically generate a stub class for hook. To help debug, you can set the generated class
/// by setting generated_* in \p InitInfo. /// name, its field name, its source name and its method name by setting generated_* in \ref
/// InitInfo.
/// \note This function thread safe (you can call it simultaneously from multiple thread) /// \note This function thread safe (you can call it simultaneously from multiple thread)
/// but it's not atomic to the same \b target_method. That means \p UnHook or \p IsUnhook does /// but it's not atomic to the same \b target_method. That means #UnHook() or #IsUnhook() does not
/// not guarantee to work properly on the same \p target_method before it returns. Also, /// guarantee to work properly on the same \p target_method before it returns. Also, simultaneously
/// simultaneously call on this function with the same \p target_method does not guarantee only one /// call on this function with the same \p target_method does not guarantee only one will success.
/// will success. If you call this with different \p hooker_object on the same target_method /// If you call this with different \p hooker_object on the same target_method simultaneously, the
/// simultaneously, the behavior is undefined. /// behavior is undefined.
[[nodiscard]] [[maybe_unused]] [[gnu::visibility("default")]] jobject Hook(JNIEnv *env, [[nodiscard, maybe_unused, gnu::visibility("default")]] jobject Hook(JNIEnv *env,
jobject target_method, jobject target_method,
jobject hooker_object, jobject hooker_object,
jobject callback_method); jobject callback_method);
/// \brief Unhook a Java function that is previously hooked. /// \brief Unhook a Java function that is previously hooked.
/// \param[in] env The Java environment. /// \param[in] env The Java environment.
@ -106,8 +109,8 @@ struct InitInfo {
/// \note Calling \p backup (the return method of #Hook()) after unhooking is undefined behavior. /// \note Calling \p backup (the return method of #Hook()) after unhooking is undefined behavior.
/// Please read #Hook()'s note for more details. /// Please read #Hook()'s note for more details.
/// \see Hook() /// \see Hook()
[[nodiscard]] [[maybe_unused]] [[gnu::visibility("default")]] bool UnHook(JNIEnv *env, [[nodiscard, maybe_unused, gnu::visibility("default")]] bool UnHook(JNIEnv *env,
jobject target_method); jobject target_method);
/// \brief Check if a Java function is hooked by LSPlant or not /// \brief Check if a Java function is hooked by LSPlant or not
/// \param[in] env The Java environment. /// \param[in] env The Java environment.
@ -115,8 +118,7 @@ struct InitInfo {
/// \return If \p method hooked, ture; otherwise, false. /// \return If \p method hooked, ture; otherwise, false.
/// Please read #Hook()'s note for more details. /// Please read #Hook()'s note for more details.
/// \see Hook() /// \see Hook()
[[nodiscard]] [[maybe_unused]] [[gnu::visibility("default")]] bool IsHooked(JNIEnv *env, [[nodiscard, maybe_unused, gnu::visibility("default")]] bool IsHooked(JNIEnv *env, jobject method);
jobject method);
/// \brief Deoptimize a method to avoid hooked callee not being called because of inline /// \brief Deoptimize a method to avoid hooked callee not being called because of inline
/// \param[in] env The Java environment. /// \param[in] env The Java environment.
@ -125,14 +127,15 @@ struct InitInfo {
/// A, and you find that your callback to B is not invoked after hooking, then it may mean A has /// A, and you find that your callback to B is not invoked after hooking, then it may mean A has
/// inlined B inside its method body. To force A to call your hooked B, you can deoptimize A and /// inlined B inside its method body. To force A to call your hooked B, you can deoptimize A and
/// then your hook can take effect. Generally, you need to find all the callers of your hooked /// then your hook can take effect. Generally, you need to find all the callers of your hooked
/// callee and that can be hardly achieve. Use this function if you are sure the deoptimized callers /// callee and that can be hardly achieve (but you can still search all callers by using DexHelper).
/// Use this function if you are sure the deoptimized callers
/// are all you need. Otherwise, it would be better to change the hook point or to deoptimize the /// are all you need. Otherwise, it would be better to change the hook point or to deoptimize the
/// whole app manually (by simple reinstall the app without uninstalled). /// whole app manually (by simple reinstall the app without uninstalled).
/// \return Indicate whether the deoptimizing succeed or not. /// \return Indicate whether the deoptimizing succeed or not.
/// \note It is safe to call deoptimizing on a hooked method because the deoptimization will /// \note It is safe to call deoptimizing on a hooked method because the deoptimization will
/// perform on the backup method instead. /// perform on the backup method instead.
[[nodiscard]] [[maybe_unused]] [[gnu::visibility("default")]] bool Deoptimize(JNIEnv *env, [[nodiscard, maybe_unused, gnu::visibility("default")]] bool Deoptimize(JNIEnv *env,
jobject method); jobject method);
/// \brief Get the registered native function pointer of a native function. It helps user to hook /// \brief Get the registered native function pointer of a native function. It helps user to hook
/// native methods directly by backing up the native function pointer this function returns and /// native methods directly by backing up the native function pointer this function returns and
@ -141,15 +144,15 @@ struct InitInfo {
/// \param[in] method The native method to get the native function pointer. /// \param[in] method The native method to get the native function pointer.
/// \return The native function pointer the \p method previously registered. If it has not been /// \return The native function pointer the \p method previously registered. If it has not been
/// registered or it is not a native method, null is returned instead. /// registered or it is not a native method, null is returned instead.
[[nodiscard]] [[maybe_unused]] [[gnu::visibility("default")]] void *GetNativeFunction( [[nodiscard, maybe_unused, gnu::visibility("default")]] void *GetNativeFunction(JNIEnv *env,
JNIEnv *env, jobject method); jobject method);
/// \brief Make a class inheritable. It will make the class non-final and make all its private /// \brief Make a class inheritable. It will make the class non-final and make all its private
/// constructors protected. /// constructors protected.
/// \param[in] env The Java environment. /// \param[in] env The Java environment.
/// \param[in] target The target class that is to make inheritable. /// \param[in] target The target class that is to make inheritable.
/// \return Indicate whether the operation has succeed. /// \return Indicate whether the operation has succeed.
[[nodiscard]] [[maybe_unused]] [[gnu::visibility("default")]] bool MakeClassInheritable( [[nodiscard, maybe_unused, gnu::visibility("default")]] bool MakeClassInheritable(JNIEnv *env,
JNIEnv *env, jclass target); jclass target);
} // namespace v1 } // namespace v1
} // namespace lsplant } // namespace lsplant

View File

@ -33,7 +33,6 @@ using art::Instrumentation;
using art::Thread; using art::Thread;
using art::gc::ScopedGCCriticalSection; using art::gc::ScopedGCCriticalSection;
using art::jit::JitCodeCache; using art::jit::JitCodeCache;
using art::mirror::Class;
using art::thread_list::ScopedSuspendAll; using art::thread_list::ScopedSuspendAll;
namespace { namespace {
@ -227,10 +226,6 @@ bool InitNative(JNIEnv *env, const HookHandler &handler) {
LOGE("Failed to init class linker"); LOGE("Failed to init class linker");
return false; return false;
} }
if (!Class::Init(env, handler)) {
LOGE("Failed to init mirror class");
return false;
}
if (!Instrumentation::Init(handler)) { if (!Instrumentation::Init(handler)) {
LOGE("Failed to init instrumentation"); LOGE("Failed to init instrumentation");
return false; return false;