[core] Cache symbol address on Zygisk (#1326)
This commit is contained in:
parent
3facd944af
commit
67fd7ca054
|
|
@ -20,9 +20,21 @@
|
|||
|
||||
check_magisk_version() {
|
||||
ui_print "- Magisk version: $MAGISK_VER_CODE"
|
||||
if [ "$MAGISK_VER_CODE" -lt 23000 ]; then
|
||||
if [ "$FLAVOR" == "riru" ]; then
|
||||
if [ "$MAGISK_VER_CODE" -lt 23000 ]; then
|
||||
ui_print "*********************************************************"
|
||||
ui_print "! Please install Magisk v23+"
|
||||
abort "*********************************************************"
|
||||
fi
|
||||
elif [ "$FLAVOR" == "zygisk" ]; then
|
||||
if [ "$MAGISK_VER_CODE" -lt 23010 ]; then
|
||||
ui_print "*********************************************************"
|
||||
ui_print "! Please install Magisk Lastest Canary (23010+)"
|
||||
abort "*********************************************************"
|
||||
fi
|
||||
else
|
||||
ui_print "*********************************************************"
|
||||
ui_print "! Please install Magisk v23+"
|
||||
ui_print "! Unsupported flavor $FLAVOR"
|
||||
abort "*********************************************************"
|
||||
fi
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#include "logging.h"
|
||||
#include "config.h"
|
||||
#include "context.h"
|
||||
#include "symbol_cache.h"
|
||||
|
||||
#define RIRU_MODULE
|
||||
#include <riru.h>
|
||||
|
|
@ -40,6 +41,7 @@ namespace lspd {
|
|||
void onModuleLoaded() {
|
||||
LOGI("onModuleLoaded: welcome to LSPosed!");
|
||||
LOGI("onModuleLoaded: version v%s (%d)", versionName, versionCode);
|
||||
InitSymbolCache(nullptr);
|
||||
Context::GetInstance()->Init();
|
||||
if constexpr (isDebug) {
|
||||
Context::GetInstance()->PreLoadDex("/system/" + kDexPath);
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#include "logging.h"
|
||||
#include "context.h"
|
||||
#include "config.h"
|
||||
#include "symbol_cache.h"
|
||||
|
||||
namespace lspd {
|
||||
namespace {
|
||||
|
|
@ -171,6 +172,107 @@ namespace lspd {
|
|||
|
||||
int *allowUnload = &allow_unload;
|
||||
|
||||
class SharedMem {
|
||||
inline static void *cutils = nullptr;
|
||||
|
||||
inline static int (*ashmem_create_region)(const char *name, std::size_t size) = nullptr;
|
||||
|
||||
inline static int (*ashmem_set_prot_region)(int fd, int prot) = nullptr;
|
||||
|
||||
inline static bool init = false;
|
||||
|
||||
static void Init() {
|
||||
if (init) return;
|
||||
cutils = dlopen("/system/lib" LP_SELECT("", "64") "/libcutils.so", 0);
|
||||
ashmem_create_region = cutils ? reinterpret_cast<decltype(ashmem_create_region)>(
|
||||
dlsym(cutils, "ashmem_create_region")) : nullptr;
|
||||
ashmem_set_prot_region = cutils ? reinterpret_cast<decltype(ashmem_set_prot_region)>(
|
||||
dlsym(cutils, "ashmem_set_prot_region")) : nullptr;
|
||||
init = true;
|
||||
}
|
||||
|
||||
int fd_ = -1;
|
||||
std::size_t size_ = 0;
|
||||
|
||||
class MappedMem {
|
||||
void *addr_ = nullptr;
|
||||
std::size_t size_ = 0;
|
||||
|
||||
friend class SharedMem;
|
||||
|
||||
MappedMem(int fd, std::size_t size, int prot, int flags, off_t offset) : addr_(
|
||||
mmap(nullptr, size, prot, flags, fd, offset)), size_(size) {
|
||||
if (addr_ == MAP_FAILED) {
|
||||
PLOGE("failed to mmap");
|
||||
addr_ = nullptr;
|
||||
size_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
MappedMem(const MappedMem &) = delete;
|
||||
|
||||
MappedMem &operator=(const MappedMem &other) = delete;
|
||||
|
||||
public:
|
||||
MappedMem(MappedMem &&other) : addr_(other.addr_), size_(other.size_) {
|
||||
other.addr_ = nullptr;
|
||||
other.size_ = 0;
|
||||
}
|
||||
|
||||
MappedMem &operator=(MappedMem &&other) {
|
||||
new(this)MappedMem(std::move(other));
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr operator bool() { return addr_; }
|
||||
|
||||
~MappedMem() {
|
||||
if (addr_) {
|
||||
munmap(addr_, size_);
|
||||
}
|
||||
}
|
||||
|
||||
constexpr auto size() const { return size_; }
|
||||
|
||||
constexpr auto get() const { return addr_; }
|
||||
};
|
||||
|
||||
public:
|
||||
MappedMem map(int prot, int flags, off_t offset) {
|
||||
return {fd_, size_, prot, flags, offset};
|
||||
}
|
||||
|
||||
constexpr bool ok() const { return fd_ > 0 && size_ > 0; }
|
||||
|
||||
SharedMem(std::string_view name, std::size_t size) {
|
||||
Init();
|
||||
if (ashmem_create_region && (fd_ = ashmem_create_region(name.data(), size)) > 0) {
|
||||
size_ = size;
|
||||
LOGD("using memfd");
|
||||
} else {
|
||||
LOGD("using tmp file");
|
||||
auto *tmp = tmpfile();
|
||||
if (tmp) {
|
||||
fd_ = fileno(tmp);
|
||||
ftruncate(fd_, size);
|
||||
size_ = size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SetProt(int prot) {
|
||||
ashmem_set_prot_region(fd_, prot);
|
||||
}
|
||||
|
||||
SharedMem() : fd_(-1), size_(0) {
|
||||
Init();
|
||||
}
|
||||
|
||||
constexpr auto get() const { return fd_; }
|
||||
|
||||
constexpr auto size() const { return size_; }
|
||||
};
|
||||
|
||||
class ZygiskModule : public zygisk::ModuleBase {
|
||||
JNIEnv *env_;
|
||||
zygisk::Api *api_;
|
||||
|
|
@ -193,6 +295,21 @@ namespace lspd {
|
|||
} else {
|
||||
LOGE("Failed to read dex fd");
|
||||
}
|
||||
if (int fd = -1, size = 0; (size = read_int(companion)) > 0 &&
|
||||
(fd = recv_fd(companion)) != -1) {
|
||||
if (auto addr = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
addr && addr != MAP_FAILED) {
|
||||
InitSymbolCache(reinterpret_cast<SymbolCache *>(addr));
|
||||
msync(addr, size, MS_SYNC);
|
||||
munmap(addr, size);
|
||||
} else {
|
||||
InitSymbolCache(nullptr);
|
||||
}
|
||||
close(fd);
|
||||
} else {
|
||||
LOGE("Failed to read symbol fd");
|
||||
InitSymbolCache(nullptr);
|
||||
}
|
||||
close(companion);
|
||||
}
|
||||
|
||||
|
|
@ -217,50 +334,59 @@ namespace lspd {
|
|||
}
|
||||
};
|
||||
|
||||
std::tuple<int, std::size_t> InitCompanion() {
|
||||
std::tuple<SharedMem, SharedMem> InitCompanion() {
|
||||
LOGI("onModuleLoaded: welcome to LSPosed!");
|
||||
LOGI("onModuleLoaded: version v%s (%d)", versionName, versionCode);
|
||||
|
||||
int (*ashmem_create_region)(const char *name, std::size_t size) = nullptr;
|
||||
int (*ashmem_set_prot_region)(int fd, int prot) = nullptr;
|
||||
|
||||
std::string path = "/data/adb/modules/"s + lspd::moduleName + "/" + kDexPath;
|
||||
int fd = open(path.data(), O_RDONLY | O_CLOEXEC);
|
||||
if (fd < 0) {
|
||||
LOGE("Failed to load dex: %s", path.data());
|
||||
return {-1, 0};
|
||||
int dex_fd = open(path.data(), O_RDONLY | O_CLOEXEC);
|
||||
if (dex_fd < 0) {
|
||||
PLOGE("Failed to load dex: %s", path.data());
|
||||
return {{}, {}};
|
||||
}
|
||||
auto fsize = lseek(fd, 0, SEEK_END);
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
auto *cutils = dlopen("/system/lib" LP_SELECT("", "64") "/libcutils.so", 0);
|
||||
ashmem_create_region = cutils ? reinterpret_cast<decltype(ashmem_create_region)>(
|
||||
dlsym(cutils, "ashmem_create_region")) : nullptr;
|
||||
ashmem_set_prot_region = cutils ? reinterpret_cast<decltype(ashmem_set_prot_region)>(
|
||||
dlsym(cutils, "ashmem_set_prot_region")) : nullptr;
|
||||
int tmp_fd = -1;
|
||||
if (void *addr = nullptr;
|
||||
ashmem_create_region && ashmem_set_prot_region &&
|
||||
(tmp_fd = ashmem_create_region("lspd.dex", fsize)) > 0 &&
|
||||
(addr = mmap(nullptr, fsize, PROT_WRITE, MAP_SHARED, tmp_fd, 0)) &&
|
||||
read(fd, addr, fsize) > 0 && munmap(addr, fsize) == 0) {
|
||||
LOGD("using memfd");
|
||||
ashmem_set_prot_region(tmp_fd, PROT_READ);
|
||||
std::swap(fd, tmp_fd);
|
||||
} else {
|
||||
LOGD("using raw fd");
|
||||
size_t dex_size = lseek(dex_fd, 0, SEEK_END);
|
||||
lseek(dex_fd, 0, SEEK_SET);
|
||||
|
||||
SharedMem dex{"lspd.dex", dex_size};
|
||||
SharedMem symbol{"symbol", sizeof(lspd::SymbolCache)};
|
||||
|
||||
if (!dex.ok() || !symbol.ok()) {
|
||||
PLOGE("Failed to allocate shared mem");
|
||||
close(dex_fd);
|
||||
return {{}, {}};
|
||||
}
|
||||
|
||||
close(tmp_fd);
|
||||
dlclose(cutils);
|
||||
return {fd, fsize};
|
||||
if (auto dex_map = dex.map(PROT_WRITE, MAP_SHARED, 0); !dex_map ||
|
||||
read(dex_fd, dex_map.get(),
|
||||
dex_map.size()) < 0) {
|
||||
PLOGE("Failed to read dex %p", dex_map.get());
|
||||
close(dex_fd);
|
||||
return {{}, {}};
|
||||
}
|
||||
|
||||
dex.SetProt(PROT_READ);
|
||||
|
||||
if (auto symbol_map = symbol.map(PROT_WRITE, MAP_SHARED, 0); symbol_map) {
|
||||
memcpy(symbol_map.get(), lspd::symbol_cache.get(), symbol_map.size());
|
||||
}
|
||||
|
||||
close(dex_fd);
|
||||
return {std::move(dex), std::move(symbol)};
|
||||
}
|
||||
|
||||
void CompanionEntry(int client) {
|
||||
using namespace std::string_literals;
|
||||
static auto[fd, size] = InitCompanion();
|
||||
if (fd > 0 && size > 0) {
|
||||
write_int(client, size);
|
||||
send_fd(client, fd);
|
||||
static auto[dex, symbol] = InitCompanion();
|
||||
LOGD("Got dex with fd=%d size=%d; Got cache with fd=%d size=%d", dex.get(),
|
||||
(int) dex.size(),
|
||||
symbol.get(), (int) symbol.size());
|
||||
if (dex.ok()) {
|
||||
write_int(client, dex.size());
|
||||
send_fd(client, dex.get());
|
||||
} else write_int(client, -1);
|
||||
if (symbol.ok()) {
|
||||
write_int(client, symbol.size());
|
||||
send_fd(client, symbol.get());
|
||||
} else write_int(client, -1);
|
||||
close(client);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -121,14 +121,14 @@ namespace art {
|
|||
if (api_level < __ANDROID_API_P__) {
|
||||
return;
|
||||
}
|
||||
DexFile_setTrustedSym = reinterpret_cast<decltype(DexFile_setTrustedSym)>(lspd::sym_setTrusted);
|
||||
lspd::HookSymNoHandle(lspd::sym_openDexFileNative, DexFile_openDexFileNative);
|
||||
lspd::HookSymNoHandle(lspd::sym_openInMemoryDexFilesNative,
|
||||
DexFile_setTrustedSym = reinterpret_cast<decltype(DexFile_setTrustedSym)>(lspd::symbol_cache->setTrusted);
|
||||
lspd::HookSymNoHandle(lspd::symbol_cache->openDexFileNative, DexFile_openDexFileNative);
|
||||
lspd::HookSymNoHandle(lspd::symbol_cache->openInMemoryDexFilesNative,
|
||||
DexFile_openInMemoryDexFilesNative);
|
||||
if (api_level == __ANDROID_API_P__) {
|
||||
lspd::HookSymNoHandle(lspd::sym_createCookieWithArray,
|
||||
lspd::HookSymNoHandle(lspd::symbol_cache->createCookieWithArray,
|
||||
DexFile_createCookieWithArray);
|
||||
lspd::HookSymNoHandle(lspd::sym_createCookieWithDirectBuffer,
|
||||
lspd::HookSymNoHandle(lspd::symbol_cache->createCookieWithDirectBuffer,
|
||||
DexFile_createCookieWithDirectBuffer);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -121,7 +121,6 @@ namespace lspd {
|
|||
}
|
||||
|
||||
void Context::Init() {
|
||||
InitSymbolCache();
|
||||
}
|
||||
|
||||
void Context::Init(JNIEnv *env) {
|
||||
|
|
@ -188,7 +187,10 @@ namespace lspd {
|
|||
void
|
||||
Context::OnNativeForkSystemServerPre(JNIEnv *env) {
|
||||
Service::instance()->InitService(env);
|
||||
skip_ = !sym_initialized;
|
||||
skip_ = !symbol_cache->initialized.test(std::memory_order_acquire);
|
||||
if (skip_) [[unlikely]] {
|
||||
LOGW("skip system server due to symbol cache");
|
||||
}
|
||||
setAllowUnload(skip_);
|
||||
}
|
||||
|
||||
|
|
@ -204,6 +206,9 @@ namespace lspd {
|
|||
FindAndCall(env, "forkSystemServerPost", "(Landroid/os/IBinder;)V", binder);
|
||||
} else skip_ = true;
|
||||
}
|
||||
if (skip_) [[unlikely]] {
|
||||
LOGW("skipped system server");
|
||||
}
|
||||
setAllowUnload(skip_);
|
||||
}
|
||||
|
||||
|
|
@ -226,7 +231,7 @@ namespace lspd {
|
|||
Service::instance()->InitService(env);
|
||||
const auto app_id = uid % PER_USER_RANGE;
|
||||
JUTFString process_name(env, nice_name);
|
||||
skip_ = !sym_initialized;
|
||||
skip_ = !symbol_cache->initialized.test(std::memory_order_acquire);
|
||||
if (!skip_ && !app_data_dir) {
|
||||
LOGD("skip injecting into %s because it has no data dir", process_name.get());
|
||||
skip_ = true;
|
||||
|
|
@ -266,7 +271,7 @@ namespace lspd {
|
|||
} else {
|
||||
auto context = Context::ReleaseInstance();
|
||||
auto service = Service::ReleaseInstance();
|
||||
art_img.reset();
|
||||
GetArt().reset();
|
||||
LOGD("skipped %s", process_name.get());
|
||||
setAllowUnload(true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -122,9 +122,9 @@ namespace lspd {
|
|||
});
|
||||
|
||||
bool InstallNativeAPI() {
|
||||
LOGD("InstallNativeAPI: %p", sym_do_dlopen);
|
||||
if (sym_do_dlopen) [[likely]] {
|
||||
HookSymNoHandle(sym_do_dlopen, do_dlopen);
|
||||
LOGD("InstallNativeAPI: %p", symbol_cache->do_dlopen);
|
||||
if (symbol_cache->do_dlopen) [[likely]] {
|
||||
HookSymNoHandle(symbol_cache->do_dlopen, do_dlopen);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ namespace lspd {
|
|||
return;
|
||||
}
|
||||
LOGD("Start to install inline hooks");
|
||||
const auto &handle_libart = *art_img;
|
||||
const auto &handle_libart = *GetArt();
|
||||
if (!handle_libart.isValid()) {
|
||||
LOGE("Failed to fetch libart.so");
|
||||
}
|
||||
|
|
@ -62,7 +62,7 @@ namespace lspd {
|
|||
art::thread_list::ScopedSuspendAll::Setup(handle_libart);
|
||||
art::gc::ScopedGCCriticalSection::Setup(handle_libart);
|
||||
art::jit::jit_code_cache::Setup(handle_libart);
|
||||
art_img.reset();
|
||||
GetArt().reset();
|
||||
LOGD("Inline hooks installed");
|
||||
}
|
||||
} // namespace lspd
|
||||
|
|
|
|||
|
|
@ -171,7 +171,7 @@ namespace lspd {
|
|||
auto binder_class = JNI_FindClass(env, "android/os/Binder");
|
||||
exec_transact_backup_methodID_ = JNI_GetMethodID(env, binder_class, "execTransact",
|
||||
"(IJJI)Z");
|
||||
if (!sym_set_table_override) {
|
||||
if (!symbol_cache->setTableOverride) {
|
||||
LOGE("set table override not found");
|
||||
}
|
||||
memcpy(&native_interface_replace_, env->functions, sizeof(JNINativeInterface));
|
||||
|
|
@ -179,8 +179,8 @@ namespace lspd {
|
|||
call_boolean_method_va_backup_ = env->functions->CallBooleanMethodV;
|
||||
native_interface_replace_.CallBooleanMethodV = &call_boolean_method_va_replace;
|
||||
|
||||
if (sym_set_table_override != nullptr) {
|
||||
reinterpret_cast<void (*)(JNINativeInterface *)>(sym_set_table_override)(
|
||||
if (symbol_cache->setTableOverride != nullptr) {
|
||||
reinterpret_cast<void (*)(JNINativeInterface *)>(symbol_cache->setTableOverride)(
|
||||
&native_interface_replace_);
|
||||
}
|
||||
if (auto activity_thread_class = JNI_FindClass(env, "android/app/IActivityManager$Stub")) {
|
||||
|
|
|
|||
|
|
@ -31,48 +31,60 @@
|
|||
#include <logging.h>
|
||||
|
||||
namespace lspd {
|
||||
bool sym_initialized = false;
|
||||
void *sym_do_dlopen = nullptr;
|
||||
void *sym_openInMemoryDexFilesNative = nullptr;
|
||||
void *sym_createCookieWithArray = nullptr;
|
||||
void *sym_createCookieWithDirectBuffer = nullptr;
|
||||
void *sym_openDexFileNative = nullptr;
|
||||
void *sym_setTrusted = nullptr;
|
||||
void *sym_set_table_override = nullptr;
|
||||
std::unique_ptr<const SandHook::ElfImg> art_img = nullptr;
|
||||
std::unique_ptr<SymbolCache> symbol_cache = std::make_unique<SymbolCache>();
|
||||
|
||||
std::unique_ptr<const SandHook::ElfImg> &GetArt() {
|
||||
static std::unique_ptr<const SandHook::ElfImg> kArtImg = nullptr;
|
||||
if (!kArtImg) {
|
||||
kArtImg = std::make_unique<SandHook::ElfImg>(kLibArtName);
|
||||
}
|
||||
return kArtImg;
|
||||
}
|
||||
|
||||
|
||||
bool FindLibArt() {
|
||||
art_img = std::make_unique<SandHook::ElfImg>(kLibArtName);
|
||||
if (!art_img->isValid()) return false;
|
||||
auto &art = GetArt();
|
||||
if (!art->isValid()) return false;
|
||||
auto api_level = GetAndroidApiLevel();
|
||||
return (sym_set_table_override = art_img->getSymbAddress<void *>(
|
||||
return (symbol_cache->setTableOverride = art->getSymbAddress<void *>(
|
||||
"_ZN3art9JNIEnvExt16SetTableOverrideEPK18JNINativeInterface")) != nullptr
|
||||
&& (api_level < __ANDROID_API_P__ || (
|
||||
(sym_openDexFileNative = art_img->getSymbAddress<void *>(
|
||||
(symbol_cache->openDexFileNative = art->getSymbAddress<void *>(
|
||||
"_ZN3artL25DexFile_openDexFileNativeEP7_JNIEnvP7_jclassP8_jstringS5_iP8_jobjectP13_jobjectArray")) &&
|
||||
(
|
||||
(sym_openInMemoryDexFilesNative = art_img->getSymbAddress<void *>(
|
||||
(symbol_cache->openInMemoryDexFilesNative = art->getSymbAddress<void *>(
|
||||
"_ZN3artL34DexFile_openInMemoryDexFilesNativeEP7_JNIEnvP7_jclassP13_jobjectArrayS5_P10_jintArrayS7_P8_jobjectS5_")) ||
|
||||
(
|
||||
(sym_createCookieWithArray = art_img->getSymbAddress<void *>(
|
||||
(symbol_cache->createCookieWithArray = art->getSymbAddress<void *>(
|
||||
"_ZN3artL29DexFile_createCookieWithArrayEP7_JNIEnvP7_jclassP11_jbyteArrayii")) &&
|
||||
(sym_createCookieWithDirectBuffer = art_img->getSymbAddress<void *>(
|
||||
(symbol_cache->createCookieWithDirectBuffer = art->getSymbAddress<void *>(
|
||||
"_ZN3artL36DexFile_createCookieWithDirectBufferEP7_JNIEnvP7_jclassP8_jobjectii"))
|
||||
)
|
||||
) &&
|
||||
(sym_setTrusted = art_img->getSymbAddress<void *>(
|
||||
(symbol_cache->setTrusted = art->getSymbAddress<void *>(
|
||||
"_ZN3artL18DexFile_setTrustedEP7_JNIEnvP7_jclassP8_jobject"))));
|
||||
}
|
||||
|
||||
void InitSymbolCache() {
|
||||
void InitSymbolCache(SymbolCache *other) {
|
||||
LOGD("InitSymbolCache");
|
||||
sym_initialized = FindLibArt();
|
||||
sym_do_dlopen = SandHook::ElfImg("/linker").getSymbAddress<void *>(
|
||||
if (other && other->initialized.test(std::memory_order_acquire)) {
|
||||
LOGD("Already initialized");
|
||||
*symbol_cache = *other;
|
||||
symbol_cache->initialized.test_and_set(std::memory_order_relaxed);
|
||||
return;
|
||||
}
|
||||
auto ok = FindLibArt();
|
||||
symbol_cache->do_dlopen = SandHook::ElfImg("/linker").getSymbAddress<void *>(
|
||||
"__dl__Z9do_dlopenPKciPK17android_dlextinfoPKv");
|
||||
if (!sym_initialized) [[unlikely]] {
|
||||
sym_initialized = false;
|
||||
art_img.reset();
|
||||
if (!ok) [[unlikely]] {
|
||||
GetArt().reset();
|
||||
LOGE("Init symbol cache failed");
|
||||
} else {
|
||||
symbol_cache->initialized.test_and_set(std::memory_order_relaxed);
|
||||
if (other) {
|
||||
*other = *symbol_cache;
|
||||
other->initialized.test_and_set(std::memory_order_acq_rel);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace lspd
|
||||
|
|
|
|||
|
|
@ -26,22 +26,44 @@
|
|||
#define LSPOSED_SYMBOL_CACHE_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace SandHook {
|
||||
class ElfImg;
|
||||
}
|
||||
|
||||
namespace lspd {
|
||||
extern bool sym_initialized;
|
||||
extern std::unique_ptr<const SandHook::ElfImg> art_img;
|
||||
extern void *sym_do_dlopen;
|
||||
extern void *sym_openInMemoryDexFilesNative;
|
||||
extern void *sym_createCookieWithArray;
|
||||
extern void *sym_createCookieWithDirectBuffer;
|
||||
extern void *sym_openDexFileNative;
|
||||
extern void *sym_setTrusted;
|
||||
extern void *sym_set_table_override;
|
||||
struct SymbolCache {
|
||||
std::atomic_flag initialized{};
|
||||
void *do_dlopen;
|
||||
void *openInMemoryDexFilesNative;
|
||||
void *createCookieWithArray;
|
||||
void *createCookieWithDirectBuffer;
|
||||
void *openDexFileNative;
|
||||
void *setTrusted;
|
||||
void *setTableOverride;
|
||||
|
||||
void InitSymbolCache();
|
||||
SymbolCache() = default;
|
||||
|
||||
SymbolCache(const SymbolCache &other) :
|
||||
do_dlopen(other.do_dlopen),
|
||||
openInMemoryDexFilesNative(other.openInMemoryDexFilesNative),
|
||||
createCookieWithArray(other.createCookieWithArray),
|
||||
createCookieWithDirectBuffer(other.createCookieWithDirectBuffer),
|
||||
openDexFileNative(other.openDexFileNative),
|
||||
setTrusted(other.setTrusted),
|
||||
setTableOverride(other.setTableOverride) {}
|
||||
|
||||
SymbolCache &operator=(const SymbolCache &other) {
|
||||
new(this)SymbolCache(other);
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
extern std::unique_ptr<SymbolCache> symbol_cache;
|
||||
|
||||
void InitSymbolCache(SymbolCache *other);
|
||||
|
||||
std::unique_ptr<const SandHook::ElfImg> &GetArt();
|
||||
}
|
||||
|
||||
#endif //LSPOSED_SYMBOL_CACHE_H
|
||||
|
|
|
|||
Loading…
Reference in New Issue