Remove regex interfaces

This commit is contained in:
LoveSy 2022-11-27 00:29:32 +08:00
parent 50471176ba
commit eaff1e850b
No known key found for this signature in database
2 changed files with 40 additions and 137 deletions

View File

@ -6,24 +6,11 @@
namespace lsplt { namespace lsplt {
inline namespace v1 { inline namespace v1 {
[[deprecated( [[maybe_unused, gnu::visibility("default")]] bool RegisterHook(ino_t ino, std::string_view symbol,
"This hooks multiple functions at once, which makes the backup not accurate. Use register_hook with the first argument as ino_t instead."), void *callback, void **backup);
maybe_unused]] bool
RegisterHook(std::string_view regex, std::string_view symbol, void *callback, void **backup);
[[maybe_unused]] bool RegisterHook(ino_t ino, std::string_view symbol, void *callback, [[maybe_unused, gnu::visibility("default")]] bool CommitHook();
void **backup);
[[deprecated("This is used with regex version of RegisterHook, which is deprecated."), [[maybe_unused, gnu::visibility("default")]] bool InvalidateBackup();
maybe_unused]] void
IgnoreHook(std::string_view regex, std::string_view symbol);
[[deprecated("This is used with regex version of RegisterHook, which is deprecated."),
maybe_unused]] void
IgnoreHook(ino_t ino, std::string_view symbol);
[[maybe_unused]] bool CommitHook();
[[maybe_unused]] bool InvalidateBackup();
} // namespace v1 } // namespace v1
} // namespace lsplt } // namespace lsplt

View File

@ -13,21 +13,13 @@
#include "elf_util.hpp" #include "elf_util.hpp"
namespace { namespace {
struct BaseInfo { struct RegisterInfo {
regex_t regex;
ino_t inode; ino_t inode;
std::string symbol; std::string symbol;
~BaseInfo() { regfree(&regex); }
};
struct RegisterInfo : BaseInfo {
void *callback; void *callback;
void **backup; void **backup;
~RegisterInfo() { regfree(&regex); }
}; };
struct IgnoreInfo : BaseInfo {};
struct MapInfo { struct MapInfo {
std::string path; std::string path;
ino_t inode; ino_t inode;
@ -36,10 +28,7 @@ struct MapInfo {
std::map<uintptr_t, uintptr_t> hooks; std::map<uintptr_t, uintptr_t> hooks;
uintptr_t backup; uintptr_t backup;
std::unique_ptr<Elf> elf; std::unique_ptr<Elf> elf;
[[nodiscard]] bool Match(const BaseInfo &info) const { [[nodiscard]] bool Match(const RegisterInfo &info) const { return info.inode == inode; }
return (info.inode != 0 && info.inode == inode) ||
(info.inode == 0 && regexec(&info.regex, path.c_str(), 0, nullptr, 0) == 0);
}
}; };
class MapInfos : public std::map<uintptr_t, MapInfo, std::greater<>> { class MapInfos : public std::map<uintptr_t, MapInfo, std::greater<>> {
@ -86,26 +75,12 @@ public:
} }
// fiter out ignored // fiter out ignored
void Filter(const std::list<RegisterInfo> &register_info, void Filter(const std::list<RegisterInfo> &register_info) {
const std::list<IgnoreInfo> &ignore_info) {
for (auto iter = begin(); iter != end();) { for (auto iter = begin(); iter != end();) {
const auto &info = iter->second; const auto &info = iter->second;
bool matched = false; bool matched = false;
for (const auto &reg : register_info) { for (const auto &reg : register_info) {
if (!info.Match(reg)) { if (info.Match(reg)) {
continue;
}
bool ignored = false;
for (const auto &ign : ignore_info) {
if (!info.Match(ign)) {
continue;
}
if (ign.symbol == reg.symbol) {
ignored = true;
break;
}
}
if (!ignored) {
matched = true; matched = true;
break; break;
} }
@ -178,43 +153,21 @@ public:
return true; return true;
} }
bool DoHook(std::list<RegisterInfo> &register_info, bool DoHook(std::list<RegisterInfo> &register_info) {
const std::list<IgnoreInfo> &ignore_info) {
bool res = true; bool res = true;
for (auto &[_, info] : *this) { for (auto &[_, info] : *this) {
for (auto iter = register_info.begin(); iter != register_info.end();) { for (auto iter = register_info.begin(); iter != register_info.end();) {
const auto &reg = *iter; const auto &reg = *iter;
if (!info.Match(reg)) { if (info.start != 0 || !info.Match(reg)) continue;
continue; if (!info.elf) info.elf = std::make_unique<Elf>(info.start);
}
bool ignored = false;
for (const auto &ign : ignore_info) {
if (!info.Match(ign)) {
continue;
}
if (ign.symbol == reg.symbol) {
ignored = true;
break;
}
}
if (ignored) {
++iter;
continue;
}
if (info.start == 0 && !info.elf) {
info.elf = std::make_unique<Elf>(info.start);
}
if (info.elf && info.elf->Valid()) { if (info.elf && info.elf->Valid()) {
for (auto addr: info.elf->FindPltAddr(reg.symbol)) { for (auto addr : info.elf->FindPltAddr(reg.symbol)) {
res = DoHook(addr, reinterpret_cast<uintptr_t>(reg.callback), res = DoHook(addr, reinterpret_cast<uintptr_t>(reg.callback),
reinterpret_cast<uintptr_t *>(reg.backup)) && res; reinterpret_cast<uintptr_t *>(reg.backup)) &&
res;
} }
} }
if (reg.inode != 0) {
iter = register_info.erase(iter); iter = register_info.erase(iter);
} else {
++iter;
}
} }
} }
return res; return res;
@ -223,7 +176,7 @@ public:
bool InvalidateBackup() { bool InvalidateBackup() {
bool res = true; bool res = true;
for (auto &[_, info] : *this) { for (auto &[_, info] : *this) {
if (info.backup) { if (!info.backup) continue;
for (auto &[addr, backup] : info.hooks) { for (auto &[addr, backup] : info.hooks) {
// store new address to backup since we don't need backup // store new address to backup since we don't need backup
backup = *reinterpret_cast<uintptr_t *>(addr); backup = *reinterpret_cast<uintptr_t *>(addr);
@ -243,81 +196,44 @@ public:
info.hooks.clear(); info.hooks.clear();
info.backup = 0; info.backup = 0;
} }
}
return res; return res;
} }
}; };
std::mutex register_mutex; std::mutex hook_mutex;
std::list<RegisterInfo> register_info; std::list<RegisterInfo> register_info;
std::mutex ignore_mutex;
std::list<IgnoreInfo> ignore_info;
MapInfos map_info; MapInfos map_info;
} // namespace } // namespace
namespace lsplt { namespace lsplt {
[[maybe_unused]] bool RegisterHook(std::string_view regex_str, std::string_view symbol,
void *callback, void **backup) {
if (regex_str.empty() || symbol.empty() || !callback) return false;
regex_t regex;
if (regcomp(&regex, regex_str.data(), REG_NOSUB) != 0) return false;
std::unique_lock lock(register_mutex);
register_info.emplace_back(RegisterInfo{{regex, 0, std::string{symbol}}, callback, backup});
return true;
}
[[maybe_unused]] bool RegisterHook(ino_t ino, std::string_view symbol, void *callback, [[maybe_unused]] bool RegisterHook(ino_t ino, std::string_view symbol, void *callback,
void **backup) { void **backup) {
if (symbol.empty() || !callback) return false; if (symbol.empty() || !callback) return false;
std::unique_lock lock(register_mutex); std::unique_lock lock(hook_mutex);
register_info.emplace_back(RegisterInfo{{{}, ino, std::string{symbol}}, callback, backup}); register_info.emplace_back(RegisterInfo{ino, std::string{symbol}, callback, backup});
return true; return true;
} }
[[maybe_unused]] void IgnoreHook(std::string_view regex, std::string_view symbol) {
if (regex.empty() || symbol.empty()) return;
regex_t reg;
if (regcomp(&reg, regex.data(), REG_NOSUB) != 0) return;
std::unique_lock lock(ignore_mutex);
ignore_info.emplace_back(IgnoreInfo{{reg, 0, std::string{symbol}}});
}
[[maybe_unused]] void IgnoreHook(ino_t ino, std::string_view symbol) {
if (symbol.empty()) return;
std::unique_lock lock(ignore_mutex);
ignore_info.emplace_back(IgnoreInfo{{regex_t{}, ino, std::string{symbol}}});
}
[[maybe_unused]] bool CommitHook() { [[maybe_unused]] bool CommitHook() {
std::unique_lock lock(register_mutex); std::unique_lock lock(hook_mutex);
if (register_info.empty()) return true; if (register_info.empty()) return true;
std::unique_lock lock2(ignore_mutex);
auto new_map_info = MapInfos::ScanMapInfo(); auto new_map_info = MapInfos::ScanMapInfo();
if (new_map_info.empty()) return false; if (new_map_info.empty()) return false;
new_map_info.Filter(register_info, ignore_info); new_map_info.Filter(register_info);
new_map_info.Merge(map_info); new_map_info.Merge(map_info);
// update to new map info // update to new map info
map_info = std::move(new_map_info); map_info = std::move(new_map_info);
return map_info.DoHook(register_info, ignore_info); return map_info.DoHook(register_info);
} }
[[gnu::destructor]] [[maybe_unused]] bool InvalidateBackup() { [[gnu::destructor]] [[maybe_unused]] bool InvalidateBackup() {
std::unique_lock lock(register_mutex); std::unique_lock lock(hook_mutex);
std::unique_lock lock2(ignore_mutex);
return map_info.InvalidateBackup(); return map_info.InvalidateBackup();
} }
} // namespace lsplt } // namespace lsplt