Skip to content

Commit

Permalink
Simplify hooking implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
ChristopherHX committed Sep 25, 2021
1 parent 9eec9d0 commit 45ab709
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 21 deletions.
24 changes: 22 additions & 2 deletions linker/linker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -663,7 +663,13 @@ class LoadTask {
auto extinfo = this->get_extinfo();
if(extinfo && extinfo->flags & ANDROID_DLEXT_MCPELAUNCHER_HOOKS) {
for(auto hook = extinfo->mcpelauncher_hooks; hook->name; hook++) {
(si_->symbols[hook->name] = std::make_shared<ElfW(Sym)>())->st_value = (ElfW(Addr))hook->value - si_->load_bias;
auto entry = std::make_shared<soinfo::HookEntry>();
entry->symbol.st_value = (ElfW(Addr))hook->value - si_->load_bias;
entry->symbol.st_info = STB_GLOBAL << 4;
entry->symbol.st_shndx = 1;
hook->value = nullptr;
entry->orig = &hook->value;
si_->symbols[hook->name] = std::move(entry);
}
}

Expand Down Expand Up @@ -2278,6 +2284,16 @@ void* do_dlopen(const char* name, int flags,
"... dlopen calling constructors: realpath=\"%s\", soname=\"%s\", handle=%p",
si->get_realpath(), si->get_soname(), handle);
si->call_constructors();
if(extinfo && extinfo->flags & ANDROID_DLEXT_MCPELAUNCHER_HOOKS) {
for(auto&& sym : si->symbols) {
// Check if this symbol isn't relocated do a fake lookup to enshure orig is set
if(sym.second->orig != nullptr && *sym.second->orig == 0) {
void* val;
do_dlsym(handle, sym.first.data(), nullptr, nullptr, &val);
}
sym.second->orig = nullptr;
}
}
failure_guard.Disable();
LD_LOG(kLogDlopen,
"... dlopen successful: realpath=\"%s\", soname=\"%s\", handle=%p",
Expand Down Expand Up @@ -2858,7 +2874,11 @@ soinfo *soinfo::load_library(const char *name, const std::unordered_map<std::str
// lib->symbols.reserve(symbols.size());
for (auto&& s : symbols) {
if(s.second) {
(lib->symbols[s.first] = std::make_shared<ElfW(Sym)>())->st_value = (ElfW(Addr))s.second;
auto entry = std::make_shared<soinfo::HookEntry>();
entry->symbol.st_value = (ElfW(Addr))s.second;
entry->symbol.st_info = STB_GLOBAL << 4;
entry->symbol.st_shndx = 1;
lib->symbols[s.first] = std::move(entry);
} else {
async_safe_format_log(2, "load_library", "Undefined symbol %s", s.first.c_str());
}
Expand Down
35 changes: 18 additions & 17 deletions linker/linker_soinfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,10 @@ void SymbolLookupList::set_dt_symbolic_lib(soinfo* lib) {
begin_ = lib ? &libs_[0] : &libs_[1];
}

bool SymbolLookupLib::needs_sysv_lookup() const {
return si_ != nullptr && (gnu_bloom_filter_ == nullptr || si_->symbols.size() > 0);
}

// Check whether a requested version matches the version on a symbol definition. There are a few
// special cases:
// - If the defining DSO has no version info at all, then any version matches.
Expand Down Expand Up @@ -148,19 +152,6 @@ soinfo_do_lookup_impl(const char* name, const version_info* vi,
name, lib->si_->get_realpath(), reinterpret_cast<void*>(lib->si_->base));
}

if (lib->si_->symbols.size()) {
// Custom overrides
auto sym = lib->si_->symbols.find(name);
if(sym != lib->si_->symbols.end()) {
// if(!strcmp("mcpelauncher_vlog", name)) {
// // throw 0;
// int i = 0;
// }
*si_found_in = lib->si_;
return sym->second.get();
}
}

const uint32_t word_num = (hash / kBloomMaskBits) & lib->gnu_maskwords_;
const ElfW(Addr) bloom_word = lib->gnu_bloom_filter_[word_num];
const uint32_t h1 = hash % kBloomMaskBits;
Expand Down Expand Up @@ -338,19 +329,29 @@ SymbolLookupLib soinfo::get_lookup_lib() {

const ElfW(Sym)* soinfo::find_symbol_by_name(SymbolName& symbol_name,
const version_info* vi) const {
void** orig = nullptr;
ElfW(Sym)* ret = nullptr;
if (this->symbols.size()) {
// Custom Library
auto sym = this->symbols.find(symbol_name.get_name());
if(sym != this->symbols.end()) {
auto n = symbol_name.get_name();

return sym->second.get();
orig = sym->second->orig;
ret = &sym->second->symbol;
}
}
if(this->bucket_) {
return is_gnu_hash() ? gnu_lookup(symbol_name, vi) : elf_lookup(symbol_name, vi);
auto&& ret2 = is_gnu_hash() ? gnu_lookup(symbol_name, vi) : elf_lookup(symbol_name, vi);
if(!ret) {
return ret2;
} else {
if(orig != nullptr) {
*orig = ret2 ? (void*)(ret2->st_value + load_bias) : nullptr;
}
return ret;
}
}
return (ElfW(Sym)*)nullptr;
return ret;
}

const ElfW(Sym)* soinfo::gnu_lookup(SymbolName& symbol_name, const version_info* vi) const {
Expand Down
8 changes: 6 additions & 2 deletions linker/linker_soinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ struct SymbolLookupLib {

soinfo* si_ = nullptr;

bool needs_sysv_lookup() const { return si_ != nullptr && gnu_bloom_filter_ == nullptr; }
bool needs_sysv_lookup() const;
};

// A list of libraries to search for a symbol.
Expand Down Expand Up @@ -442,7 +442,11 @@ struct soinfo {
std::vector<TlsDynamicResolverArg> tlsdesc_args_;

public:
std::unordered_map<std::string, std::shared_ptr<ElfW(Sym)>> symbols;
struct HookEntry {
ElfW(Sym) symbol;
void** orig;
};
std::unordered_map<std::string, std::shared_ptr<HookEntry>> symbols;
};

// This function is used by dlvsym() to calculate hash of sym_ver
Expand Down

0 comments on commit 45ab709

Please sign in to comment.