Skip to content

Commit

Permalink
Modularize hook helper
Browse files Browse the repository at this point in the history
  • Loading branch information
yujincheng08 committed Aug 5, 2024
1 parent 39334ba commit 14b753e
Show file tree
Hide file tree
Showing 15 changed files with 543 additions and 574 deletions.
99 changes: 42 additions & 57 deletions lsplant/src/main/jni/art/mirror/class.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -3,38 +3,36 @@ module;
#include <parallel_hashmap/phmap.h>

#include "logging.hpp"
#include "utils/hook_helper.hpp"

export module clazz;

import common;
import art_method;
import thread;
import handle;
import hook_helper;

namespace lsplant::art::mirror {

export class Class {
private:
CREATE_MEM_FUNC_SYMBOL_ENTRY(const char *, GetDescriptor, Class *thiz, std::string *storage) {
if (GetDescriptorSym) [[likely]]
return GetDescriptorSym(thiz, storage);
else
return "";
}
inline static MemberFunction<
"_ZN3art6mirror5Class13GetDescriptorEPNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE",
Class, const char *(std::string *)>
GetDescriptor_;

CREATE_MEM_FUNC_SYMBOL_ENTRY(const dex::ClassDef *, GetClassDef, Class *thiz) {
if (GetClassDefSym) [[likely]]
return GetClassDefSym(thiz);
return nullptr;
}
inline static MemberFunction<"_ZN3art6mirror5Class11GetClassDefEv", Class,
const dex::ClassDef *()>
GetClassDef_;

using BackupMethods = phmap::flat_hash_map<art::ArtMethod *, void *>;
inline static phmap::flat_hash_map<const art::Thread *,
phmap::flat_hash_map<const dex::ClassDef *, BackupMethods>>
backup_methods_;
inline static std::mutex backup_methods_lock_;

inline static uint8_t initialized_status = 0;

static void BackupClassMethods(const dex::ClassDef *class_def, art::Thread *self) {
BackupMethods out;
if (!class_def) return;
Expand Down Expand Up @@ -64,62 +62,57 @@ export class Class {
}
}

CREATE_HOOK_STUB_ENTRY(
"_ZN3art6mirror5Class9SetStatusENS_6HandleIS1_EENS_11ClassStatusEPNS_6ThreadE", void,
SetClassStatus, (TrivialHandle<Class> h, uint8_t new_status, Thread *self), {
inline static Hooker<
"_ZN3art6mirror5Class9SetStatusENS_6HandleIS1_EENS_11ClassStatusEPNS_6ThreadE",
void(TrivialHandle<Class>, uint8_t, Thread *)>
SetClassStatus_ = +[](TrivialHandle<Class> h, uint8_t new_status, Thread *self) {
if (new_status == initialized_status) {
BackupClassMethods(h->GetClassDef(), self);
BackupClassMethods(GetClassDef_(h.Get()), self);
}
return backup(h, new_status, self);
});
return SetClassStatus_(h, new_status, self);
};

CREATE_HOOK_STUB_ENTRY(
"_ZN3art6mirror5Class9SetStatusENS_6HandleIS1_EENS1_6StatusEPNS_6ThreadE", void, SetStatus,
(Handle<Class> h, int new_status, Thread *self), {
inline static Hooker<"_ZN3art6mirror5Class9SetStatusENS_6HandleIS1_EENS1_6StatusEPNS_6ThreadE",
void(Handle<Class>, int, Thread *)>
SetStatus_ = +[](Handle<Class> h, int new_status, Thread *self) {
if (new_status == static_cast<int>(initialized_status)) {
BackupClassMethods(h->GetClassDef(), self);
BackupClassMethods(GetClassDef_(h.Get()), self);
}
return backup(h, new_status, self);
});
return SetStatus_(h, new_status, self);
};

CREATE_HOOK_STUB_ENTRY(
"_ZN3art6mirror5Class9SetStatusENS_6HandleIS1_EENS1_6StatusEPNS_6ThreadE", void,
TrivialSetStatus, (TrivialHandle<Class> h, uint32_t new_status, Thread *self), {
inline static Hooker<"_ZN3art6mirror5Class9SetStatusENS_6HandleIS1_EENS1_6StatusEPNS_6ThreadE",
void(TrivialHandle<Class>, uint32_t, Thread *)>
TrivialSetStatus_ = +[](TrivialHandle<Class> h, uint32_t new_status, Thread *self) {
if (new_status == initialized_status) {
BackupClassMethods(h->GetClassDef(), self);
BackupClassMethods(GetClassDef_(h.Get()), self);
}
return backup(h, new_status, self);
});
return TrivialSetStatus_(h, new_status, self);
};

CREATE_MEM_HOOK_STUB_ENTRY("_ZN3art6mirror5Class9SetStatusENS1_6StatusEPNS_6ThreadE", void,
ClassSetStatus, (Class * thiz, int new_status, Thread *self), {
if (new_status == static_cast<int>(initialized_status)) {
BackupClassMethods(thiz->GetClassDef(), self);
}
return backup(thiz, new_status, self);
});

inline static uint8_t initialized_status = 0;
inline static Hooker<"_ZN3art6mirror5Class9SetStatusENS1_6StatusEPNS_6ThreadE",
void(Class *, int, Thread *)>
ClassSetStatus_ = +[](Class *thiz, int new_status, Thread *self) {
if (new_status == static_cast<int>(initialized_status)) {
BackupClassMethods(GetClassDef_(thiz), self);
}
return ClassSetStatus_(thiz, new_status, self);
};

public:
static bool Init(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")) {
if (!handler.dlsym(GetDescriptor_) || !handler.dlsym(GetClassDef_)) {
return false;
}

int sdk_int = GetAndroidApiLevel();

if (sdk_int < __ANDROID_API_O__) {
if (!HookSyms(handler, SetStatus, ClassSetStatus)) {
if (!handler.hook(SetStatus_, ClassSetStatus_)) {
return false;
}
} else {
if (!HookSyms(handler, SetClassStatus, TrivialSetStatus)) {
if (!handler.hook(SetClassStatus_, TrivialSetStatus_)) {
return false;
}
}
Expand All @@ -137,22 +130,14 @@ export class Class {
return true;
}

const char *GetDescriptor(std::string *storage) {
if (GetDescriptorSym) {
return GetDescriptor(this, storage);
}
return "";
}
const char *GetDescriptor(std::string *storage) { return GetDescriptor_(this, storage); }

std::string GetDescriptor() {
std::string storage;
return GetDescriptor(&storage);
}

const dex::ClassDef *GetClassDef() {
if (GetClassDefSym) return GetClassDef(this);
return nullptr;
}
const dex::ClassDef *GetClassDef() { return GetClassDef_(this); }

static auto PopBackup(const dex::ClassDef *class_def, art::Thread *self) {
BackupMethods methods;
Expand Down
87 changes: 49 additions & 38 deletions lsplant/src/main/jni/art/runtime/art_method.cxx
Original file line number Diff line number Diff line change
@@ -1,45 +1,58 @@
module;

#include <atomic>
#include <string>

#include "logging.hpp"
#include "utils/hook_helper.hpp"

export module art_method;

import common;
import hook_helper;

namespace lsplant::art {
namespace mirror {
class Class;
}

export class ArtMethod {
CREATE_FUNC_SYMBOL_ENTRY(std::string, PrettyMethod, ArtMethod *thiz, bool with_signature) {
if (thiz == nullptr) [[unlikely]]
return "null";
else if (PrettyMethodSym) [[likely]]
return PrettyMethodSym(thiz, with_signature);
else
return "null sym";
}

CREATE_MEM_FUNC_SYMBOL_ENTRY(void, ThrowInvocationTimeError, ArtMethod *thiz) {
if (thiz && ThrowInvocationTimeErrorSym) [[likely]]
return ThrowInvocationTimeErrorSym(thiz);
}

CREATE_FUNC_SYMBOL_ENTRY(const char *, GetMethodShorty, JNIEnv *env, jmethodID mid) {
if (GetMethodShortySym) [[likely]]
return GetMethodShortySym(env, mid);
return nullptr;
inline static MemberFunction<"_ZN3art9ArtMethod12PrettyMethodEPS0_b", ArtMethod,
std::string(bool)>
PrettyMethod_;

inline static Function<"_ZN3art12PrettyMethodEPNS_9ArtMethodEb",
std::string(ArtMethod *thiz, bool with_signature)>
PrettyMethodStatic_;

inline static Function<"_ZN3art12PrettyMethodEPNS_6mirror9ArtMethodEb",
std::string(ArtMethod *thiz, bool with_signature)>
PrettyMethodMirror_;

inline static Function<"_ZN3artL15GetMethodShortyEP7_JNIEnvP10_jmethodID",
const char *(JNIEnv *env, jmethodID method)>
GetMethodShortyL_;
inline static Function<"_ZN3art15GetMethodShortyEP7_JNIEnvP10_jmethodID",
const char *(JNIEnv *env, jmethodID mid)>
GetMethodShorty_;

inline static MemberFunction<"_ZN3art9ArtMethod24ThrowInvocationTimeErrorEv", ArtMethod, void()>
ThrowInvocationTimeError_;

inline static Function<"artInterpreterToCompiledCodeBridge", void()>
art_interpreter_to_compiled_code_bridge_;

inline void ThrowInvocationTimeError() {
if (ThrowInvocationTimeError_) {
[[likely]] ThrowInvocationTimeError_(this);
}
}

CREATE_FUNC_SYMBOL_ENTRY(void, art_interpreter_to_compiled_code_bridge) {}

inline void ThrowInvocationTimeError() { ThrowInvocationTimeError(this); }

public:
inline static const char *GetMethodShorty(JNIEnv *env, jobject method) {
return GetMethodShorty(env, env->FromReflectedMethod(method));
if (GetMethodShortyL_) {
return GetMethodShortyL_(env, env->FromReflectedMethod(method));
}
return GetMethodShorty_(env, env->FromReflectedMethod(method));
}

void SetNonCompilable() {
Expand Down Expand Up @@ -101,7 +114,7 @@ export class ArtMethod {
if (interpreter_entry_point_offset) [[unlikely]] {
*reinterpret_cast<void **>(reinterpret_cast<uintptr_t>(this) +
interpreter_entry_point_offset) =
reinterpret_cast<void *>(art_interpreter_to_compiled_code_bridgeSym);
reinterpret_cast<void *>(&art_interpreter_to_compiled_code_bridge_);
}
}

Expand Down Expand Up @@ -130,7 +143,11 @@ export class ArtMethod {
}

std::string PrettyMethod(bool with_signature = true) {
return PrettyMethod(this, with_signature);
if (PrettyMethod_) [[likely]]
return PrettyMethod_(this, with_signature);
if (PrettyMethodStatic_) return PrettyMethodStatic_(this, with_signature);
if (PrettyMethodMirror_) return PrettyMethodMirror_(this, with_signature);
return "null sym";
}

mirror::Class *GetDeclaringClass() {
Expand Down Expand Up @@ -229,7 +246,7 @@ export class ArtMethod {
JNI_GetObjectField(
env,
JNI_ToReflectedField(env, executable,
JNI_GetFieldID(env, executable, name, sig), false),
JNI_GetFieldID(env, executable, name, sig), false),
art_field_field),
field_offset);
};
Expand All @@ -256,17 +273,13 @@ export class ArtMethod {
}
if (sdk_int < __ANDROID_API_Q__) kAccFastInterpreterToInterpreterInvoke = 0;

if (!RETRIEVE_FUNC_SYMBOL(GetMethodShorty,
"_ZN3artL15GetMethodShortyEP7_JNIEnvP10_jmethodID", true) &&
!RETRIEVE_FUNC_SYMBOL(GetMethodShorty,
"_ZN3art15GetMethodShortyEP7_JNIEnvP10_jmethodID")) {
if (!handler.dlsym(GetMethodShortyL_, true) && !handler.dlsym(GetMethodShorty_)) {
LOGE("Failed to find GetMethodShorty");
return false;
}

!RETRIEVE_FUNC_SYMBOL(PrettyMethod, "_ZN3art9ArtMethod12PrettyMethodEPS0_b") &&
!RETRIEVE_FUNC_SYMBOL(PrettyMethod, "_ZN3art12PrettyMethodEPNS_9ArtMethodEb") &&
!RETRIEVE_FUNC_SYMBOL(PrettyMethod, "_ZN3art12PrettyMethodEPNS_6mirror9ArtMethodEb");
handler.dlsym(PrettyMethod_) || handler.dlsym(PrettyMethodStatic_) ||
handler.dlsym(PrettyMethodMirror_);

if (sdk_int <= __ANDROID_API_O__) [[unlikely]] {
auto abstract_method_error = JNI_FindClass(env, "java/lang/AbstractMethodError");
Expand All @@ -281,8 +294,7 @@ export class ArtMethod {
LOGE("Failed to find Executable.getName");
return false;
}
RETRIEVE_MEM_FUNC_SYMBOL(ThrowInvocationTimeError,
"_ZN3art9ArtMethod24ThrowInvocationTimeErrorEv");
handler.dlsym(ThrowInvocationTimeError_);
auto abstract_method = FromReflectedMethod(
env, JNI_ToReflectedMethod(env, executable, executable_get_name, false).get());
uint32_t access_flags = abstract_method->GetAccessFlags();
Expand All @@ -301,8 +313,7 @@ export class ArtMethod {
kAccCompileDontBother = 0;
}
if (sdk_int <= __ANDROID_API_M__) [[unlikely]] {
if (!RETRIEVE_FUNC_SYMBOL(art_interpreter_to_compiled_code_bridge,
"artInterpreterToCompiledCodeBridge")) {
if (!handler.dlsym(art_interpreter_to_compiled_code_bridge_)) {
return false;
}
if (sdk_int >= __ANDROID_API_L_MR1__) {
Expand Down
Loading

0 comments on commit 14b753e

Please sign in to comment.