mirror of
https://github.com/LSPosed/LSPlant.git
synced 2025-05-04 20:42:02 +08:00
Allow customize generated class
This commit is contained in:
parent
752c85a030
commit
3132a66692
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user