Use PLT hook from Zygisk API(v4)
This commit is contained in:
parent
4d8e01176f
commit
534e3930ae
|
|
@ -76,59 +76,6 @@ inline bool RegisterNativeMethodsInternal(JNIEnv *env, std::string_view class_na
|
||||||
RegisterNativeMethodsInternal(env, GetNativeBridgeSignature() + #class_name, gMethods, \
|
RegisterNativeMethodsInternal(env, GetNativeBridgeSignature() + #class_name, gMethods, \
|
||||||
arraysize(gMethods))
|
arraysize(gMethods))
|
||||||
|
|
||||||
static dev_t dev = 0;
|
|
||||||
static ino_t inode = 0;
|
|
||||||
static std::vector<std::pair<const char *, void **>> plt_hook_saved = {};
|
|
||||||
|
|
||||||
inline int HookPLT(void *art_symbol, void *callback, void **backup, bool save = true) {
|
|
||||||
auto symbol = reinterpret_cast<const char *>(art_symbol);
|
|
||||||
|
|
||||||
if (GetArt()->isStripped()) {
|
|
||||||
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 && *backup != nullptr) {
|
|
||||||
if (save) plt_hook_saved.emplace_back(symbol, backup);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (auto addr = GetArt()->getSymbAddress(symbol); addr) {
|
|
||||||
HookInline(addr, callback, backup);
|
|
||||||
} else if (*backup == nullptr && isDebug) {
|
|
||||||
LOGW("Failed to {} Art symbol {}", save ? "hook" : "unhook", symbol);
|
|
||||||
}
|
|
||||||
return *backup == nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int UnhookPLT(void *original) {
|
|
||||||
Dl_info info;
|
|
||||||
|
|
||||||
if (!dladdr(original, &info) || info.dli_sname != nullptr) return 1;
|
|
||||||
if (!GetArt()->isStripped()) return UnhookInline(original);
|
|
||||||
|
|
||||||
auto hook_iter =
|
|
||||||
std::find_if(plt_hook_saved.begin(), plt_hook_saved.end(),
|
|
||||||
[info](auto record) { return strcmp(record.first, info.dli_sname) == 0; });
|
|
||||||
void *stub = nullptr;
|
|
||||||
if (hook_iter != plt_hook_saved.end() &&
|
|
||||||
HookPLT(original, *(hook_iter->second), &stub, false)) {
|
|
||||||
plt_hook_saved.erase(hook_iter);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline std::string GetNativeBridgeSignature() {
|
inline std::string GetNativeBridgeSignature() {
|
||||||
const auto &obfs_map = ConfigBridge::GetInstance()->obfuscation_map();
|
const auto &obfs_map = ConfigBridge::GetInstance()->obfuscation_map();
|
||||||
static auto signature = obfs_map.at("org.lsposed.lspd.nativebridge.");
|
static auto signature = obfs_map.at("org.lsposed.lspd.nativebridge.");
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <jni.h>
|
#include <jni.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
#define ZYGISK_API_VERSION 4
|
#define ZYGISK_API_VERSION 4
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,62 +17,62 @@
|
||||||
* Copyright (C) 2021 - 2022 LSPosed Contributors
|
* Copyright (C) 2021 - 2022 LSPosed Contributors
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
#include "zygisk.hpp"
|
|
||||||
#include "logging.h"
|
|
||||||
#include "loader.h"
|
|
||||||
#include "config_impl.h"
|
#include "config_impl.h"
|
||||||
|
#include "loader.h"
|
||||||
|
#include "logging.h"
|
||||||
#include "magisk_loader.h"
|
#include "magisk_loader.h"
|
||||||
#include "symbol_cache.h"
|
#include "symbol_cache.h"
|
||||||
|
#include "zygisk.hpp"
|
||||||
|
|
||||||
namespace lspd {
|
namespace lspd {
|
||||||
int allow_unload = 0;
|
int allow_unload = 0;
|
||||||
int *allowUnload = &allow_unload;
|
int *allowUnload = &allow_unload;
|
||||||
|
|
||||||
class ZygiskModule : public zygisk::ModuleBase {
|
class ZygiskModule : public zygisk::ModuleBase {
|
||||||
JNIEnv *env_;
|
JNIEnv *env_;
|
||||||
zygisk::Api *api_;
|
zygisk::Api *api_;
|
||||||
|
|
||||||
void onLoad(zygisk::Api *api, JNIEnv *env) override {
|
void onLoad(zygisk::Api *api, JNIEnv *env) override {
|
||||||
env_ = env;
|
env_ = env;
|
||||||
api_ = api;
|
api_ = api;
|
||||||
MagiskLoader::Init();
|
MagiskLoader::Init(api);
|
||||||
ConfigImpl::Init();
|
ConfigImpl::Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void preAppSpecialize(zygisk::AppSpecializeArgs *args) override {
|
||||||
|
MagiskLoader::GetInstance()->OnNativeForkAndSpecializePre(
|
||||||
|
env_, args->uid, args->gids, args->nice_name,
|
||||||
|
args->is_child_zygote ? *args->is_child_zygote : false, args->app_data_dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
void postAppSpecialize(const zygisk::AppSpecializeArgs *args) override {
|
||||||
|
MagiskLoader::GetInstance()->OnNativeForkAndSpecializePost(env_, args->nice_name,
|
||||||
|
args->app_data_dir);
|
||||||
|
if (*allowUnload) api_->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
|
||||||
|
}
|
||||||
|
|
||||||
|
void preServerSpecialize([[maybe_unused]] zygisk::ServerSpecializeArgs *args) override {
|
||||||
|
MagiskLoader::GetInstance()->OnNativeForkSystemServerPre(env_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void postServerSpecialize([[maybe_unused]] const zygisk::ServerSpecializeArgs *args) override {
|
||||||
|
if (__system_property_find("ro.vendor.product.ztename")) {
|
||||||
|
auto *process = env_->FindClass("android/os/Process");
|
||||||
|
auto *set_argv0 = env_->GetStaticMethodID(process, "setArgV0", "(Ljava/lang/String;)V");
|
||||||
|
auto *name = env_->NewStringUTF("system_server");
|
||||||
|
env_->CallStaticVoidMethod(process, set_argv0, name);
|
||||||
|
env_->DeleteLocalRef(name);
|
||||||
|
env_->DeleteLocalRef(process);
|
||||||
}
|
}
|
||||||
|
MagiskLoader::GetInstance()->OnNativeForkSystemServerPost(env_);
|
||||||
void preAppSpecialize(zygisk::AppSpecializeArgs *args) override {
|
if (*allowUnload) api_->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
|
||||||
MagiskLoader::GetInstance()->OnNativeForkAndSpecializePre(
|
}
|
||||||
env_, args->uid, args->gids, args->nice_name,
|
};
|
||||||
args->is_child_zygote ? *args->is_child_zygote : false, args->app_data_dir);
|
} // namespace lspd
|
||||||
}
|
|
||||||
|
|
||||||
void postAppSpecialize(const zygisk::AppSpecializeArgs *args) override {
|
|
||||||
MagiskLoader::GetInstance()->OnNativeForkAndSpecializePost(env_, args->nice_name, args->app_data_dir);
|
|
||||||
if (*allowUnload) api_->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
|
|
||||||
}
|
|
||||||
|
|
||||||
void preServerSpecialize([[maybe_unused]] zygisk::ServerSpecializeArgs *args) override {
|
|
||||||
MagiskLoader::GetInstance()->OnNativeForkSystemServerPre(env_);
|
|
||||||
}
|
|
||||||
|
|
||||||
void postServerSpecialize([[maybe_unused]] const zygisk::ServerSpecializeArgs *args) override {
|
|
||||||
if (__system_property_find("ro.vendor.product.ztename")) {
|
|
||||||
auto *process = env_->FindClass("android/os/Process");
|
|
||||||
auto *set_argv0 = env_->GetStaticMethodID(process, "setArgV0",
|
|
||||||
"(Ljava/lang/String;)V");
|
|
||||||
auto *name = env_->NewStringUTF("system_server");
|
|
||||||
env_->CallStaticVoidMethod(process, set_argv0, name);
|
|
||||||
env_->DeleteLocalRef(name);
|
|
||||||
env_->DeleteLocalRef(process);
|
|
||||||
}
|
|
||||||
MagiskLoader::GetInstance()->OnNativeForkSystemServerPost(env_);
|
|
||||||
if (*allowUnload) api_->setOption(zygisk::DLCLOSE_MODULE_LIBRARY);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} //namespace lspd
|
|
||||||
|
|
||||||
REGISTER_ZYGISK_MODULE(lspd::ZygiskModule);
|
REGISTER_ZYGISK_MODULE(lspd::ZygiskModule);
|
||||||
|
|
|
||||||
|
|
@ -23,11 +23,15 @@
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
#include <sys/sysmacros.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cinttypes>
|
||||||
|
|
||||||
|
#include "../src/native_api.h"
|
||||||
#include "config_impl.h"
|
#include "config_impl.h"
|
||||||
#include "elf_util.h"
|
#include "elf_util.h"
|
||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
#include "native_util.h"
|
|
||||||
#include "service.h"
|
#include "service.h"
|
||||||
#include "symbol_cache.h"
|
#include "symbol_cache.h"
|
||||||
#include "utils/jni_helper.hpp"
|
#include "utils/jni_helper.hpp"
|
||||||
|
|
@ -50,6 +54,105 @@ constexpr int PER_USER_RANGE = 100000;
|
||||||
static constexpr uid_t kAidInjected = INJECTED_AID;
|
static constexpr uid_t kAidInjected = INJECTED_AID;
|
||||||
static constexpr uid_t kAidInet = 3003;
|
static constexpr uid_t kAidInet = 3003;
|
||||||
|
|
||||||
|
std::vector<MapInfo> MapInfo::Scan(std::string_view pid) {
|
||||||
|
constexpr static auto kPermLength = 5;
|
||||||
|
constexpr static auto kMapEntry = 7;
|
||||||
|
std::vector<MapInfo> info;
|
||||||
|
auto path = "/proc/" + std::string{pid} + "/maps";
|
||||||
|
auto maps = std::unique_ptr<FILE, decltype(&fclose)>{fopen(path.c_str(), "r"), &fclose};
|
||||||
|
if (maps) {
|
||||||
|
char *line = nullptr;
|
||||||
|
size_t len = 0;
|
||||||
|
ssize_t read;
|
||||||
|
while ((read = getline(&line, &len, maps.get())) > 0) {
|
||||||
|
line[read - 1] = '\0';
|
||||||
|
uintptr_t start = 0;
|
||||||
|
uintptr_t end = 0;
|
||||||
|
uintptr_t off = 0;
|
||||||
|
ino_t inode = 0;
|
||||||
|
unsigned int dev_major = 0;
|
||||||
|
unsigned int dev_minor = 0;
|
||||||
|
std::array<char, kPermLength> perm{'\0'};
|
||||||
|
int path_off;
|
||||||
|
if (sscanf(line, "%" PRIxPTR "-%" PRIxPTR " %4s %" PRIxPTR " %x:%x %lu %n%*s", &start,
|
||||||
|
&end, perm.data(), &off, &dev_major, &dev_minor, &inode,
|
||||||
|
&path_off) != kMapEntry) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
while (path_off < read && isspace(line[path_off])) path_off++;
|
||||||
|
auto &ref = info.emplace_back(MapInfo{start, end, 0, perm[3] == 'p', off,
|
||||||
|
static_cast<dev_t>(makedev(dev_major, dev_minor)),
|
||||||
|
inode, line + path_off});
|
||||||
|
if (perm[0] == 'r') ref.perms |= PROT_READ;
|
||||||
|
if (perm[1] == 'w') ref.perms |= PROT_WRITE;
|
||||||
|
if (perm[2] == 'x') ref.perms |= PROT_EXEC;
|
||||||
|
}
|
||||||
|
free(line);
|
||||||
|
}
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MagiskLoader::InitializeZygiskApi(zygisk::Api *api) {
|
||||||
|
std::vector<std::pair<const char *, void **>> plt_hook_saved = {};
|
||||||
|
|
||||||
|
const std::string libArtPath = GetArt()->name();
|
||||||
|
const auto maps = MapInfo::Scan();
|
||||||
|
const auto libArtMap = std::find_if(maps.begin(), maps.end(),
|
||||||
|
[libArtPath](auto it) { return it.path == libArtPath; });
|
||||||
|
const dev_t dev = libArtMap->inode;
|
||||||
|
const ino_t inode = libArtMap->dev;
|
||||||
|
|
||||||
|
auto HookPLT = [dev, inode, &plt_hook_saved, api](void *art_symbol, void *callback,
|
||||||
|
void **backup, bool save = true) {
|
||||||
|
auto symbol = reinterpret_cast<const char *>(art_symbol);
|
||||||
|
|
||||||
|
if (GetArt()->isStripped()) {
|
||||||
|
api->pltHookRegister(dev, inode, symbol, callback, backup);
|
||||||
|
if (api->pltHookCommit() && *backup != nullptr) {
|
||||||
|
if (save) plt_hook_saved.emplace_back(symbol, backup);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (auto addr = GetArt()->getSymbAddress(symbol); addr) {
|
||||||
|
HookInline(addr, callback, backup);
|
||||||
|
} else if (*backup == nullptr && isDebug) {
|
||||||
|
LOGW("Failed to {} Art symbol {}", save ? "hook" : "unhook", symbol);
|
||||||
|
}
|
||||||
|
return (int)(*backup == nullptr);
|
||||||
|
};
|
||||||
|
|
||||||
|
auto UnhookPLT = [HookPLT, &plt_hook_saved](void *original) {
|
||||||
|
Dl_info info;
|
||||||
|
|
||||||
|
if (!dladdr(original, &info) || info.dli_sname != nullptr) return 1;
|
||||||
|
if (!GetArt()->isStripped()) return UnhookInline(original);
|
||||||
|
|
||||||
|
auto hook_iter =
|
||||||
|
std::find_if(plt_hook_saved.begin(), plt_hook_saved.end(),
|
||||||
|
[info](auto record) { return strcmp(record.first, info.dli_sname) == 0; });
|
||||||
|
void *stub = nullptr;
|
||||||
|
if (hook_iter != plt_hook_saved.end() &&
|
||||||
|
HookPLT(original, *(hook_iter->second), &stub, false)) {
|
||||||
|
plt_hook_saved.erase(hook_iter);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
initInfo = lsplant::InitInfo{
|
||||||
|
.inline_hooker =
|
||||||
|
[HookPLT](auto t, auto r) {
|
||||||
|
void *bk = nullptr;
|
||||||
|
return HookPLT(t, r, &bk) == 0 ? bk : nullptr;
|
||||||
|
},
|
||||||
|
.inline_unhooker = [UnhookPLT](auto t) { return UnhookPLT(t) == 0; },
|
||||||
|
.art_symbol_resolver = [](auto symbol) { return GetArt()->getSymbAddress(symbol); },
|
||||||
|
.art_symbol_prefix_resolver =
|
||||||
|
[](auto symbol) { return GetArt()->getSymbPrefixFirstAddress(symbol); },
|
||||||
|
.is_plt_hook = true};
|
||||||
|
}
|
||||||
|
|
||||||
void MagiskLoader::LoadDex(JNIEnv *env, PreloadedDex &&dex) {
|
void MagiskLoader::LoadDex(JNIEnv *env, PreloadedDex &&dex) {
|
||||||
auto classloader = JNI_FindClass(env, "java/lang/ClassLoader");
|
auto classloader = JNI_FindClass(env, "java/lang/ClassLoader");
|
||||||
auto getsyscl_mid = JNI_GetStaticMethodID(env, classloader, "getSystemClassLoader",
|
auto getsyscl_mid = JNI_GetStaticMethodID(env, classloader, "getSystemClassLoader",
|
||||||
|
|
@ -115,17 +218,6 @@ void MagiskLoader::OnNativeForkSystemServerPost(JNIEnv *env) {
|
||||||
instance->HookBridge(*this, env);
|
instance->HookBridge(*this, env);
|
||||||
|
|
||||||
// always inject into system server
|
// always inject into system server
|
||||||
lsplant::InitInfo initInfo{
|
|
||||||
.inline_hooker =
|
|
||||||
[](auto t, auto r) {
|
|
||||||
void *bk = nullptr;
|
|
||||||
return HookPLT(t, r, &bk) == 0 ? bk : nullptr;
|
|
||||||
},
|
|
||||||
.inline_unhooker = [](auto t) { return UnhookPLT(t) == 0; },
|
|
||||||
.art_symbol_resolver = [](auto symbol) { return GetArt()->getSymbAddress(symbol); },
|
|
||||||
.art_symbol_prefix_resolver =
|
|
||||||
[](auto symbol) { return GetArt()->getSymbPrefixFirstAddress(symbol); },
|
|
||||||
.is_plt_hook = true};
|
|
||||||
InitArtHooker(env, initInfo);
|
InitArtHooker(env, initInfo);
|
||||||
InitHooks(env);
|
InitHooks(env);
|
||||||
SetupEntryClass(env);
|
SetupEntryClass(env);
|
||||||
|
|
@ -187,17 +279,6 @@ void MagiskLoader::OnNativeForkAndSpecializePost(JNIEnv *env, jstring nice_name,
|
||||||
auto binder =
|
auto binder =
|
||||||
skip_ ? ScopedLocalRef<jobject>{env, nullptr} : instance->RequestBinder(env, nice_name);
|
skip_ ? ScopedLocalRef<jobject>{env, nullptr} : instance->RequestBinder(env, nice_name);
|
||||||
if (binder) {
|
if (binder) {
|
||||||
lsplant::InitInfo initInfo{
|
|
||||||
.inline_hooker =
|
|
||||||
[](auto t, auto r) {
|
|
||||||
void *bk = nullptr;
|
|
||||||
return HookPLT(t, r, &bk) == 0 ? bk : nullptr;
|
|
||||||
},
|
|
||||||
.inline_unhooker = [](auto t) { return UnhookPLT(t) == 0; },
|
|
||||||
.art_symbol_resolver = [](auto symbol) { return GetArt()->getSymbAddress(symbol); },
|
|
||||||
.art_symbol_prefix_resolver =
|
|
||||||
[](auto symbol) { return GetArt()->getSymbPrefixFirstAddress(symbol); },
|
|
||||||
.is_plt_hook = true};
|
|
||||||
auto [dex_fd, size] = instance->RequestLSPDex(env, binder);
|
auto [dex_fd, size] = instance->RequestLSPDex(env, binder);
|
||||||
auto obfs_map = instance->RequestObfuscationMap(env, binder);
|
auto obfs_map = instance->RequestObfuscationMap(env, binder);
|
||||||
ConfigBridge::GetInstance()->obfuscation_map(std::move(obfs_map));
|
ConfigBridge::GetInstance()->obfuscation_map(std::move(obfs_map));
|
||||||
|
|
|
||||||
|
|
@ -23,36 +23,70 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "../api/zygisk.hpp"
|
||||||
#include "context.h"
|
#include "context.h"
|
||||||
|
|
||||||
namespace lspd {
|
namespace lspd {
|
||||||
class MagiskLoader : public Context {
|
class MagiskLoader : public Context {
|
||||||
public:
|
public:
|
||||||
inline static void Init() {
|
inline static void Init(zygisk::Api *api) {
|
||||||
instance_ = std::make_unique<MagiskLoader>();
|
instance_ = std::make_unique<MagiskLoader>();
|
||||||
}
|
GetInstance()->InitializeZygiskApi(api);
|
||||||
|
}
|
||||||
|
|
||||||
inline static MagiskLoader *GetInstance() {
|
inline static MagiskLoader *GetInstance() {
|
||||||
return static_cast<MagiskLoader*>(instance_.get());
|
return static_cast<MagiskLoader *>(instance_.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnNativeForkAndSpecializePre(JNIEnv *env, jint uid, jintArray &gids, jstring &nice_name,
|
void OnNativeForkAndSpecializePre(JNIEnv *env, jint uid, jintArray &gids, jstring &nice_name,
|
||||||
jboolean is_child_zygote, jstring app_data_dir);
|
jboolean is_child_zygote, jstring app_data_dir);
|
||||||
|
|
||||||
void OnNativeForkAndSpecializePost(JNIEnv *env, jstring nice_name, jstring app_dir);
|
void OnNativeForkAndSpecializePost(JNIEnv *env, jstring nice_name, jstring app_dir);
|
||||||
|
|
||||||
void OnNativeForkSystemServerPost(JNIEnv *env);
|
void OnNativeForkSystemServerPost(JNIEnv *env);
|
||||||
|
|
||||||
void OnNativeForkSystemServerPre(JNIEnv *env);
|
void OnNativeForkSystemServerPre(JNIEnv *env);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void LoadDex(JNIEnv *env, PreloadedDex &&dex) override;
|
void LoadDex(JNIEnv *env, PreloadedDex &&dex) override;
|
||||||
|
|
||||||
void SetupEntryClass(JNIEnv *env) override;
|
void SetupEntryClass(JNIEnv *env) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool skip_ = false;
|
bool skip_ = false;
|
||||||
|
lsplant::InitInfo initInfo;
|
||||||
|
|
||||||
static void setAllowUnload(bool unload);
|
void InitializeZygiskApi(zygisk::Api *api);
|
||||||
};
|
static void setAllowUnload(bool unload);
|
||||||
} // namespace lspd
|
};
|
||||||
|
|
||||||
|
struct MapInfo {
|
||||||
|
/// \brief The start address of the memory region.
|
||||||
|
uintptr_t start;
|
||||||
|
/// \brief The end address of the memory region.
|
||||||
|
uintptr_t end;
|
||||||
|
/// \brief The permissions of the memory region. This is a bit mask of the following values:
|
||||||
|
/// - PROT_READ
|
||||||
|
/// - PROT_WRITE
|
||||||
|
/// - PROT_EXEC
|
||||||
|
uint8_t perms;
|
||||||
|
/// \brief Whether the memory region is private.
|
||||||
|
bool is_private;
|
||||||
|
/// \brief The offset of the memory region.
|
||||||
|
uintptr_t offset;
|
||||||
|
/// \brief The device number of the memory region.
|
||||||
|
/// Major can be obtained by #major()
|
||||||
|
/// Minor can be obtained by #minor()
|
||||||
|
dev_t dev;
|
||||||
|
/// \brief The inode number of the memory region.
|
||||||
|
ino_t inode;
|
||||||
|
/// \brief The path of the memory region.
|
||||||
|
std::string path;
|
||||||
|
|
||||||
|
/// \brief Scans /proc/self/maps and returns a list of \ref MapInfo entries.
|
||||||
|
/// This is useful to find out the inode of the library to hook.
|
||||||
|
/// \param[in] pid The process id to scan. This is "self" by default.
|
||||||
|
/// \return A list of \ref MapInfo entries.
|
||||||
|
static std::vector<MapInfo> Scan(std::string_view pid = "self");
|
||||||
|
};
|
||||||
|
} // namespace lspd
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue