Avoid resolving `libart` symbols twice
LSPlt is only used to hook libart symbols. The file `native_util.h` is reformatted by clangd. Fallback to Dobby if LSPlt fails.
This commit is contained in:
parent
75e300532e
commit
1d7de6c78e
|
|
@ -31,7 +31,6 @@ namespace lspd {
|
|||
|
||||
//#define LOG_DISABLED
|
||||
//#define DEBUG
|
||||
using lsplant::operator""_tstr;
|
||||
|
||||
inline bool constexpr Is64() {
|
||||
#if defined(__LP64__)
|
||||
|
|
|
|||
|
|
@ -19,27 +19,30 @@
|
|||
*/
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include "lsplt.hpp"
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include "elf_util.h"
|
||||
#include "lsplt.hpp"
|
||||
#include "symbol_cache.h"
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wunused-value"
|
||||
#pragma once
|
||||
|
||||
#include <context.h>
|
||||
#include "utils/jni_helper.hpp"
|
||||
#include "logging.h"
|
||||
#include "config.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include "../src/native_api.h"
|
||||
#include "config.h"
|
||||
#include "config_bridge.h"
|
||||
#include "logging.h"
|
||||
#include "utils/jni_helper.hpp"
|
||||
|
||||
namespace lspd {
|
||||
|
||||
[[gnu::always_inline]]
|
||||
inline bool RegisterNativeMethodsInternal(JNIEnv *env,
|
||||
std::string_view class_name,
|
||||
const JNINativeMethod *methods,
|
||||
jint method_count) {
|
||||
|
||||
inline bool RegisterNativeMethodsInternal(JNIEnv *env, std::string_view class_name,
|
||||
const JNINativeMethod *methods, jint method_count) {
|
||||
auto clazz = Context::GetInstance()->FindClassFromCurrentLoader(env, class_name.data());
|
||||
if (clazz.get() == nullptr) {
|
||||
LOGF("Couldn't find class: {}", class_name.data());
|
||||
|
|
@ -49,87 +52,74 @@ inline bool RegisterNativeMethodsInternal(JNIEnv *env,
|
|||
}
|
||||
|
||||
#if defined(__cplusplus)
|
||||
#define _NATIVEHELPER_JNI_MACRO_CAST(to) \
|
||||
reinterpret_cast<to>
|
||||
#define _NATIVEHELPER_JNI_MACRO_CAST(to) reinterpret_cast<to>
|
||||
#else
|
||||
#define _NATIVEHELPER_JNI_MACRO_CAST(to) \
|
||||
(to)
|
||||
#define _NATIVEHELPER_JNI_MACRO_CAST(to) (to)
|
||||
#endif
|
||||
|
||||
#ifndef LSP_NATIVE_METHOD
|
||||
#define LSP_NATIVE_METHOD(className, functionName, signature) \
|
||||
{ #functionName, \
|
||||
signature, \
|
||||
_NATIVEHELPER_JNI_MACRO_CAST(void*) (Java_org_lsposed_lspd_nativebridge_## className ## _ ## functionName) \
|
||||
}
|
||||
{#functionName, signature, \
|
||||
_NATIVEHELPER_JNI_MACRO_CAST(void *)( \
|
||||
Java_org_lsposed_lspd_nativebridge_##className##_##functionName)}
|
||||
#endif
|
||||
|
||||
#define JNI_START [[maybe_unused]] JNIEnv *env, [[maybe_unused]] jclass clazz
|
||||
|
||||
#ifndef LSP_DEF_NATIVE_METHOD
|
||||
#define LSP_DEF_NATIVE_METHOD(ret, className, functionName, ...) \
|
||||
extern "C" ret Java_org_lsposed_lspd_nativebridge_## className ## _ ## functionName (JNI_START, ## __VA_ARGS__)
|
||||
extern "C" ret Java_org_lsposed_lspd_nativebridge_##className##_##functionName(JNI_START, \
|
||||
##__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#define REGISTER_LSP_NATIVE_METHODS(class_name) \
|
||||
RegisterNativeMethodsInternal(env, GetNativeBridgeSignature() + #class_name, gMethods, arraysize(gMethods))
|
||||
RegisterNativeMethodsInternal(env, GetNativeBridgeSignature() + #class_name, gMethods, \
|
||||
arraysize(gMethods))
|
||||
|
||||
static std::vector<std::tuple<dev_t, ino_t, const char *, void **>> plt_hook_list = {};
|
||||
static auto scan_maps = lsplt::MapInfo::Scan();
|
||||
static dev_t dev = 0;
|
||||
static ino_t inode = 0;
|
||||
static std::vector<std::pair<std::string_view, void **>> plt_hook_saved = {};
|
||||
|
||||
inline int plt_hook(const char *lib, const char *symbol, void *callback, void **backup) {
|
||||
dev_t dev = 0;
|
||||
ino_t inode = 0;
|
||||
for (auto map : scan_maps) {
|
||||
if (map.path == lib) {
|
||||
inline int HookArtFunction(void *original, void *callback, void **backup, bool save = true) {
|
||||
auto symbol = *reinterpret_cast<std::string_view *>(original);
|
||||
if (dev == 0 || inode == 0) {
|
||||
auto libart_path = GetArt()->name();
|
||||
for (auto map : lsplt::MapInfo::Scan()) {
|
||||
if (map.path == libart_path) {
|
||||
inode = map.inode;
|
||||
dev = map.dev;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto result = lsplt::RegisterHook(dev, inode, symbol, callback, backup) && lsplt::CommitHook();
|
||||
if (result) {
|
||||
plt_hook_list.emplace_back(dev, inode, symbol, backup);
|
||||
if (result && *backup != nullptr) {
|
||||
if (save) plt_hook_saved.emplace_back(symbol, backup);
|
||||
} else if (auto addr = GetArt()->getSymbAddress(symbol); addr) {
|
||||
Dl_info info;
|
||||
if (dladdr(addr, &info) && info.dli_sname != nullptr && info.dli_sname == symbol)
|
||||
HookFunction(addr, callback, backup);
|
||||
} else if (*backup == nullptr && isDebug) {
|
||||
LOGW("Failed to {} Art symbol {}", save ? "hook" : "unhook", symbol);
|
||||
}
|
||||
return *backup == nullptr;
|
||||
}
|
||||
|
||||
inline int UnhookArtFunction(void *original) {
|
||||
std::string_view func_name = *reinterpret_cast<std::string_view *>(original);
|
||||
auto hook_iter = std::find_if(plt_hook_saved.begin(), plt_hook_saved.end(),
|
||||
[func_name](auto record) { return record.first == func_name; });
|
||||
|
||||
void *stub = nullptr;
|
||||
if (hook_iter != plt_hook_saved.end() &&
|
||||
HookArtFunction(original, *(hook_iter->second), &stub, false)) {
|
||||
plt_hook_saved.erase(hook_iter);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
inline int HookFunction(void *original, void *replace, void **backup) {
|
||||
Dl_info info;
|
||||
if (dladdr(original, &info)) {
|
||||
if constexpr (isDebug) {
|
||||
LOGD("Hooking {} ({}) from {} ({})",
|
||||
info.dli_sname ? info.dli_sname : "(unknown symbol)", info.dli_saddr,
|
||||
info.dli_fname ? info.dli_fname : "(unknown file)", info.dli_fbase);
|
||||
}
|
||||
if (info.dli_sname != NULL && info.dli_fname != NULL)
|
||||
return plt_hook(info.dli_fname, info.dli_sname, replace, backup);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
inline int UnhookFunction(void *original) {
|
||||
Dl_info info;
|
||||
if (dladdr(original, &info)) {
|
||||
if constexpr (isDebug) {
|
||||
LOGD("Unhooking {} ({}) from {} ({})",
|
||||
info.dli_sname ? info.dli_sname : "(unknown symbol)", info.dli_saddr,
|
||||
info.dli_fname ? info.dli_fname : "(unknown file)", info.dli_fbase);
|
||||
}
|
||||
|
||||
for (const auto [dev, inode, symbol, backup] : plt_hook_list) {
|
||||
if (info.dli_sname == symbol) {
|
||||
auto result = lsplt::RegisterHook(dev, inode, symbol, backup, nullptr)
|
||||
&& lsplt::CommitHook();
|
||||
return 1 - result;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
inline std::string GetNativeBridgeSignature() {
|
||||
const auto &obfs_map = ConfigBridge::GetInstance()->obfuscation_map();
|
||||
static auto signature = obfs_map.at("org.lsposed.lspd.nativebridge.");
|
||||
|
|
|
|||
|
|
@ -48,7 +48,6 @@
|
|||
|
||||
namespace lspd {
|
||||
|
||||
using lsplant::operator""_tstr;
|
||||
std::list<NativeOnModuleLoaded> moduleLoadedCallbacks;
|
||||
std::list<std::string> moduleNativeLibs;
|
||||
std::unique_ptr<void, std::function<void(void *)>> protected_page(
|
||||
|
|
@ -58,8 +57,8 @@ namespace lspd {
|
|||
const auto[entries] = []() {
|
||||
auto *entries = new(protected_page.get()) NativeAPIEntries{
|
||||
.version = 2,
|
||||
.hookFunc = &DobbyHookFunction,
|
||||
.unhookFunc = &DobbyUnhookFunction,
|
||||
.hookFunc = &HookFunction,
|
||||
.unhookFunc = &UnhookFunction,
|
||||
};
|
||||
|
||||
mprotect(protected_page.get(), 4096, PROT_READ);
|
||||
|
|
@ -71,7 +70,7 @@ namespace lspd {
|
|||
return InstallNativeAPI({
|
||||
.inline_hooker = [](auto t, auto r) {
|
||||
void* bk = nullptr;
|
||||
return DobbyHookFunction(t, r, &bk) == 0 ? bk : nullptr;
|
||||
return HookFunction(t, r, &bk) == 0 ? bk : nullptr;
|
||||
},
|
||||
});
|
||||
}();
|
||||
|
|
|
|||
|
|
@ -52,23 +52,25 @@ namespace lspd {
|
|||
|
||||
void RegisterNativeLib(const std::string &library_name);
|
||||
|
||||
inline int DobbyHookFunction(void *original, void *replace, void **backup) {
|
||||
inline int HookFunction(void *original, void *replace, void **backup) {
|
||||
if constexpr (isDebug) {
|
||||
Dl_info info;
|
||||
if (dladdr(original, &info))
|
||||
LOGD("Dobby hooking {} ({}) from {} ({})",
|
||||
info.dli_sname ? info.dli_sname : "(unknown symbol)", info.dli_saddr,
|
||||
info.dli_sname ? info.dli_sname : "(unknown symbol)",
|
||||
info.dli_saddr ? info.dli_saddr : original,
|
||||
info.dli_fname ? info.dli_fname : "(unknown file)", info.dli_fbase);
|
||||
}
|
||||
return DobbyHook(original, reinterpret_cast<dobby_dummy_func_t>(replace), reinterpret_cast<dobby_dummy_func_t *>(backup));
|
||||
}
|
||||
|
||||
inline int DobbyUnhookFunction(void *original) {
|
||||
inline int UnhookFunction(void *original) {
|
||||
if constexpr (isDebug) {
|
||||
Dl_info info;
|
||||
if (dladdr(original, &info))
|
||||
LOGD("Dobby unhooking {} ({}) from {} ({})",
|
||||
info.dli_sname ? info.dli_sname : "(unknown symbol)", info.dli_saddr,
|
||||
info.dli_sname ? info.dli_sname : "(unknown symbol)",
|
||||
info.dli_saddr ? info.dli_saddr : original,
|
||||
info.dli_fname ? info.dli_fname : "(unknown file)", info.dli_fbase);
|
||||
}
|
||||
return DobbyDestroy(original);
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 9ce26897d3fc9a07ded56b3da612d154c1031a62
|
||||
Subproject commit 2009a1922c63e5838eaeff79eacf821d4f6b536f
|
||||
|
|
@ -119,10 +119,10 @@ namespace lspd {
|
|||
lsplant::InitInfo initInfo{
|
||||
.inline_hooker = [](auto t, auto r) {
|
||||
void* bk = nullptr;
|
||||
return HookFunction(t, r, &bk) == 0 ? bk : nullptr;
|
||||
return HookArtFunction(t, r, &bk) == 0 ? bk : nullptr;
|
||||
},
|
||||
.inline_unhooker = [](auto t) {
|
||||
return UnhookFunction(t) == 0 ;
|
||||
return UnhookArtFunction(t) == 0 ;
|
||||
},
|
||||
.art_symbol_resolver = [](auto symbol) {
|
||||
return GetArt()->getSymbAddress(symbol);
|
||||
|
|
@ -198,10 +198,10 @@ namespace lspd {
|
|||
lsplant::InitInfo initInfo{
|
||||
.inline_hooker = [](auto t, auto r) {
|
||||
void* bk = nullptr;
|
||||
return HookFunction(t, r, &bk) == 0 ? bk : nullptr;
|
||||
return HookArtFunction(t, r, &bk) == 0 ? bk : nullptr;
|
||||
},
|
||||
.inline_unhooker = [](auto t) {
|
||||
return UnhookFunction(t) == 0;
|
||||
return UnhookArtFunction(t) == 0;
|
||||
},
|
||||
.art_symbol_resolver = [](auto symbol){
|
||||
return GetArt()->getSymbAddress(symbol);
|
||||
|
|
|
|||
Loading…
Reference in New Issue