Allow customize generated class

This commit is contained in:
LoveSy 2022-02-18 10:01:40 +08:00
parent 752c85a030
commit 3132a66692
2 changed files with 46 additions and 9 deletions

View File

@ -35,9 +35,20 @@ struct InitInfo {
InlineUnhookFunType inline_unhooker;
/// \brief The symbol resolver to \p libart.so. Must not be null.
ArtSymbolResolver art_symbol_resolver;
/// \brief The generated class name. Must not be empty. It contains a field and a method
/// and they could be set by \p generated_field_name and \p generated_method_name respectively.
std::string_view generated_class_name = "LSPHooker_";
/// \brief The generated source name. Could be empty.
std::string_view generated_source_name = "LSP";
/// \brief The generated field name. Must not be empty.
std::string_view generated_field_name = "hooker";
/// \brief The generated class name. Must not be emtpy. If {target} is set,
/// it will follows the name of the target.
std::string_view generated_method_name = "{target}";
};
/// \brief Initialize LSPlant for procceding hook.
/// \brief Initialize LSPlant for the proceeding hook.
/// It mainly prefetch needed symbols and hook some functions.
/// \param[in] env The Java environment. Must not be null.
/// \param[in] info The information for initialized. \ref InitInfo.
@ -71,6 +82,9 @@ bool Init(JNIEnv *env, const InitInfo &info);
/// 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
/// if fails.
/// \note This function will automatically generate a stub class for hook. To help debug, you
/// can set the generated class name, its field name, its source name and its method name
/// by setting generated_* in \p InitInfo.
/// \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
/// not guarantee to work properly on the same \p target_method before it returns. Also,

View File

@ -76,6 +76,31 @@ jclass in_memory_class_loader = nullptr;
jmethodID in_memory_class_loader_init = nullptr;
jmethodID load_class = nullptr;
std::string generated_class_name;
std::string generated_source_name;
std::string generated_field_name;
std::string generated_method_name;
bool InitConfig(const InitInfo &info) {
if (info.generated_class_name.empty()) {
LOGE("generated class name cannot be empty");
return false;
}
generated_class_name = info.generated_class_name;
if (info.generated_field_name.empty()) {
LOGE("generated field name cannot be empty");
return false;
}
generated_field_name = info.generated_field_name;
if (info.generated_method_name.empty()) {
LOGE("generated method name cannot be empty");
return false;
}
generated_method_name = info.generated_method_name;
generated_source_name = info.generated_source_name;
return true;
}
bool InitJNI(JNIEnv *env) {
auto executable = JNI_FindClass(env, "java/lang/reflect/Executable");
if (!executable) {
@ -204,20 +229,18 @@ BuildDex(JNIEnv *env, jobject class_loader,
static_cast<char>(param)));
}
// TODO(yujincheng08): customize it
ClassBuilder cbuilder{ dex_file.MakeClass("LspHooker_") };
// TODO(yujincheng08): customize it
cbuilder.set_source_file("LSP");
ClassBuilder cbuilder{ dex_file.MakeClass(generated_class_name) };
if (!generated_source_name.empty()) cbuilder.set_source_file(generated_source_name);
auto hooker_type = TypeDescriptor::FromClassname(hooker_class.data());
// TODO(yujincheng08): customize it
auto *hooker_field = cbuilder.CreateField("hooker", hooker_type)
auto *hooker_field = cbuilder.CreateField(generated_field_name, hooker_type)
.access_flags(dex::kAccStatic)
.Encode();
auto hook_builder{ cbuilder.CreateMethod(
method_name.data(), Prototype{ return_type, parameter_types }) };
generated_method_name == "{target}" ? method_name.data() : generated_method_name,
Prototype{ return_type, parameter_types }) };
// allocate tmp first because of wide
auto tmp{ hook_builder.AllocRegister() };
hook_builder.BuildConst(tmp, static_cast<int>(parameter_types.size()));
@ -420,7 +443,7 @@ using ::lsplant::IsHooked;
[[maybe_unused]]
bool Init(JNIEnv *env, const InitInfo &info) {
bool static kInit = InitJNI(env) && InitNative(env, info);
bool static kInit = InitConfig(info) && InitJNI(env) && InitNative(env, info);
return kInit;
}