From c9ff65f4766602e158e8456aa5d358279ff74519 Mon Sep 17 00:00:00 2001 From: caikelun Date: Thu, 12 Dec 2024 15:30:52 +0800 Subject: [PATCH] Optimize the performance of shadowhook_hook_sym_addr function in arm64. --- shadowhook/src/main/cpp/arch/arm/sh_inst.c | 9 +++- shadowhook/src/main/cpp/arch/arm/sh_inst.h | 3 +- shadowhook/src/main/cpp/arch/arm64/sh_inst.c | 15 +++++- shadowhook/src/main/cpp/arch/arm64/sh_inst.h | 2 +- shadowhook/src/main/cpp/sh_exit.c | 16 +++---- shadowhook/src/main/cpp/sh_linker.c | 28 ++++++------ shadowhook/src/main/cpp/sh_linker.h | 6 +-- shadowhook/src/main/cpp/sh_switch.c | 26 ++++++----- shadowhook/src/main/cpp/sh_switch.h | 5 +- shadowhook/src/main/cpp/sh_task.c | 48 ++++++++------------ 10 files changed, 82 insertions(+), 76 deletions(-) diff --git a/shadowhook/src/main/cpp/arch/arm/sh_inst.c b/shadowhook/src/main/cpp/arch/arm/sh_inst.c index a044d64..2fe7001 100644 --- a/shadowhook/src/main/cpp/arch/arm/sh_inst.c +++ b/shadowhook/src/main/cpp/arch/arm/sh_inst.c @@ -34,6 +34,7 @@ #include "sh_config.h" #include "sh_enter.h" #include "sh_exit.h" +#include "sh_linker.h" #include "sh_log.h" #include "sh_sig.h" #include "sh_t16.h" @@ -462,11 +463,15 @@ static int sh_inst_hook_arm_without_exit(sh_inst_t *self, uintptr_t target_addr, } int sh_inst_hook(sh_inst_t *self, uintptr_t target_addr, xdl_info_t *dlinfo, uintptr_t new_addr, - uintptr_t *orig_addr, uintptr_t *orig_addr2) { + uintptr_t *orig_addr, uintptr_t *orig_addr2, bool ignore_symbol_check) { + int r; + if (NULL == dlinfo->dli_fbase) { + if (0 != (r = sh_linker_get_dlinfo_by_addr((void *)target_addr, dlinfo, ignore_symbol_check))) return r; + } + self->enter_addr = sh_enter_alloc(); if (0 == self->enter_addr) return SHADOWHOOK_ERRNO_HOOK_ENTER; - int r; if (SH_UTIL_IS_THUMB(target_addr)) { #ifdef SH_CONFIG_TRY_WITH_EXIT if (0 == (r = sh_inst_hook_thumb_with_exit(self, target_addr, dlinfo, new_addr, orig_addr, orig_addr2))) diff --git a/shadowhook/src/main/cpp/arch/arm/sh_inst.h b/shadowhook/src/main/cpp/arch/arm/sh_inst.h index 9213f9e..e4dc188 100644 --- a/shadowhook/src/main/cpp/arch/arm/sh_inst.h +++ b/shadowhook/src/main/cpp/arch/arm/sh_inst.h @@ -22,6 +22,7 @@ // Created by Kelun Cai (caikelun@bytedance.com) on 2021-04-11. #pragma once +#include #include #include "xdl.h" @@ -37,7 +38,7 @@ typedef struct { } sh_inst_t; int sh_inst_hook(sh_inst_t *self, uintptr_t target_addr, xdl_info_t *dlinfo, uintptr_t new_addr, - uintptr_t *orig_addr, uintptr_t *orig_addr2); + uintptr_t *orig_addr, uintptr_t *orig_addr2, bool ignore_symbol_check); int sh_inst_unhook(sh_inst_t *self, uintptr_t target_addr); void sh_inst_free_after_dlclose(sh_inst_t *self, uintptr_t target_addr); diff --git a/shadowhook/src/main/cpp/arch/arm64/sh_inst.c b/shadowhook/src/main/cpp/arch/arm64/sh_inst.c index 5b40f68..2329370 100644 --- a/shadowhook/src/main/cpp/arch/arm64/sh_inst.c +++ b/shadowhook/src/main/cpp/arch/arm64/sh_inst.c @@ -31,6 +31,7 @@ #include "sh_config.h" #include "sh_enter.h" #include "sh_exit.h" +#include "sh_linker.h" #include "sh_log.h" #include "sh_sig.h" #include "sh_util.h" @@ -84,7 +85,8 @@ static int sh_inst_hook_with_exit(sh_inst_t *self, uintptr_t target_addr, xdl_in uintptr_t pc = target_addr; self->backup_len = 4; - if (dlinfo->dli_ssize < self->backup_len) return SHADOWHOOK_ERRNO_HOOK_SYMSZ; + // Any function should have at least one instruction, + // so the arm64 function symbol size must be greater than or equal to 4. // alloc an exit for absolute jump sh_a64_absolute_jump_with_br(self->exit, new_addr); @@ -155,7 +157,7 @@ static int sh_inst_hook_without_exit(sh_inst_t *self, uintptr_t target_addr, xdl } int sh_inst_hook(sh_inst_t *self, uintptr_t target_addr, xdl_info_t *dlinfo, uintptr_t new_addr, - uintptr_t *orig_addr, uintptr_t *orig_addr2) { + uintptr_t *orig_addr, uintptr_t *orig_addr2, bool ignore_symbol_check) { self->enter_addr = sh_enter_alloc(); if (0 == self->enter_addr) return SHADOWHOOK_ERRNO_HOOK_ENTER; @@ -163,9 +165,18 @@ int sh_inst_hook(sh_inst_t *self, uintptr_t target_addr, xdl_info_t *dlinfo, uin #ifdef SH_CONFIG_TRY_WITH_EXIT if (0 == (r = sh_inst_hook_with_exit(self, target_addr, dlinfo, new_addr, orig_addr, orig_addr2))) return r; #endif + + if (NULL == dlinfo->dli_fbase) { + if (ignore_symbol_check) { + dlinfo->dli_ssize = 1024; // big enough + } else { + if (0 != (r = sh_linker_get_dlinfo_by_addr((void *)target_addr, dlinfo, false))) goto err; + } + } if (0 == (r = sh_inst_hook_without_exit(self, target_addr, dlinfo, new_addr, orig_addr, orig_addr2))) return r; +err: // hook failed if (NULL != orig_addr) *orig_addr = 0; if (NULL != orig_addr2) *orig_addr2 = 0; diff --git a/shadowhook/src/main/cpp/arch/arm64/sh_inst.h b/shadowhook/src/main/cpp/arch/arm64/sh_inst.h index d89d366..8efabe5 100644 --- a/shadowhook/src/main/cpp/arch/arm64/sh_inst.h +++ b/shadowhook/src/main/cpp/arch/arm64/sh_inst.h @@ -38,7 +38,7 @@ typedef struct { } sh_inst_t; int sh_inst_hook(sh_inst_t *self, uintptr_t target_addr, xdl_info_t *dlinfo, uintptr_t new_addr, - uintptr_t *orig_addr, uintptr_t *orig_addr2); + uintptr_t *orig_addr, uintptr_t *orig_addr2, bool ignore_symbol_check); int sh_inst_unhook(sh_inst_t *self, uintptr_t target_addr); void sh_inst_free_after_dlclose(sh_inst_t *self, uintptr_t target_addr); diff --git a/shadowhook/src/main/cpp/sh_exit.c b/shadowhook/src/main/cpp/sh_exit.c index 0f44d87..06b5645 100644 --- a/shadowhook/src/main/cpp/sh_exit.c +++ b/shadowhook/src/main/cpp/sh_exit.c @@ -65,10 +65,8 @@ static void sh_exit_init_out_library(void) { sh_trampo_init_mgr(&sh_exit_trampo_mgr, SH_EXIT_PAGE_NAME, SH_EXIT_SZ, SH_EXIT_DELAY_SEC); } -static int sh_exit_alloc_out_library(uintptr_t *exit_addr, uintptr_t pc, xdl_info_t *dlinfo, uint8_t *exit, - size_t range_low, size_t range_high) { - (void)dlinfo; - +static int sh_exit_alloc_out_library(uintptr_t *exit_addr, uintptr_t pc, uint8_t *exit, size_t range_low, + size_t range_high) { uintptr_t addr = sh_trampo_alloc_near(&sh_exit_trampo_mgr, pc, range_low, range_high); if (0 == addr) return -1; @@ -321,10 +319,10 @@ static int sh_exit_alloc_in_library(uintptr_t *exit_addr, uintptr_t pc, xdl_info sh_exit_elf_info_t *elfinfo = sh_exit_find_elf_info_by_pc(pc); if (NULL == elfinfo) { // get dlinfo by pc - if (NULL == dlinfo) { - xdl_info_t dlinfo_obj; - dlinfo = &dlinfo_obj; - if (0 != (r = sh_linker_get_dlinfo_by_addr((void *)pc, dlinfo, NULL, 0, NULL, 0, true))) goto end; + if (NULL == dlinfo->dli_fbase || NULL == dlinfo->dlpi_phdr) { + xdl_info_t dlinfo_tmp; + dlinfo = &dlinfo_tmp; + if (0 != (r = sh_linker_get_dlinfo_by_addr((void *)pc, dlinfo, true))) goto end; } // create elfinfo by dlinfo @@ -406,7 +404,7 @@ int sh_exit_alloc(uintptr_t *exit_addr, uint16_t *exit_type, uintptr_t pc, xdl_i // (1) try out-library mode first. Because ELF gaps are a valuable non-renewable resource. *exit_type = SH_EXIT_TYPE_OUT_LIBRARY; - r = sh_exit_alloc_out_library(exit_addr, pc, dlinfo, exit, range_low, range_high); + r = sh_exit_alloc_out_library(exit_addr, pc, exit, range_low, range_high); if (0 == r) goto ok; // (2) try in-library mode. diff --git a/shadowhook/src/main/cpp/sh_linker.c b/shadowhook/src/main/cpp/sh_linker.c index 3ea0e74..cffbde1 100644 --- a/shadowhook/src/main/cpp/sh_linker.c +++ b/shadowhook/src/main/cpp/sh_linker.c @@ -209,11 +209,11 @@ int sh_linker_register_dlopen_post_callback(sh_linker_dlopen_post_t post) { } // do hook - int (*hook)(uintptr_t, uintptr_t, uintptr_t *, size_t *, xdl_info_t *) = + int (*hook)(uintptr_t, uintptr_t, uintptr_t *, size_t *, xdl_info_t *, bool) = SHADOWHOOK_IS_SHARED_MODE ? sh_switch_hook : sh_switch_hook_invisible; size_t backup_len = 0; int r = hook((uintptr_t)dlinfo.dli_saddr, (uintptr_t)sh_linker_proxy_dlopen, - (uintptr_t *)&sh_linker_orig_dlopen, &backup_len, &dlinfo); + (uintptr_t *)&sh_linker_orig_dlopen, &backup_len, &dlinfo, false); // do record sh_recorder_add_hook(r, true, (uintptr_t)dlinfo.dli_saddr, SH_LINKER_BASENAME, dlinfo.dli_sname, @@ -492,7 +492,7 @@ static int sh_linker_hook_call_ctors_dtors(xdl_info_t *call_constructors_dlinfo, int r_hook_dtors = INT_MAX; size_t backup_len_ctors = 0; size_t backup_len_dtors = 0; - int (*hook)(uintptr_t, uintptr_t, uintptr_t *, size_t *, xdl_info_t *) = + int (*hook)(uintptr_t, uintptr_t, uintptr_t *, size_t *, xdl_info_t *, bool) = SHADOWHOOK_IS_SHARED_MODE ? sh_switch_hook : sh_switch_hook_invisible; #if !SH_LINKER_HOOK_WITH_DL_MUTEX @@ -505,9 +505,9 @@ static int sh_linker_hook_call_ctors_dtors(xdl_info_t *call_constructors_dlinfo, // hook soinfo::call_constructors() SH_LOG_INFO("linker: hook soinfo::call_constructors"); - r_hook_ctors = - hook((uintptr_t)call_constructors_dlinfo->dli_saddr, (uintptr_t)sh_linker_proxy_soinfo_call_ctors, - (uintptr_t *)&sh_linker_orig_soinfo_call_ctors, &backup_len_ctors, call_constructors_dlinfo); + r_hook_ctors = hook( + (uintptr_t)call_constructors_dlinfo->dli_saddr, (uintptr_t)sh_linker_proxy_soinfo_call_ctors, + (uintptr_t *)&sh_linker_orig_soinfo_call_ctors, &backup_len_ctors, call_constructors_dlinfo, false); if (__predict_false(0 != r_hook_ctors)) { #if SH_LINKER_HOOK_WITH_DL_MUTEX pthread_mutex_unlock(g_dl_mutex); @@ -519,7 +519,7 @@ static int sh_linker_hook_call_ctors_dtors(xdl_info_t *call_constructors_dlinfo, SH_LOG_INFO("linker: hook soinfo::call_destructors"); r_hook_dtors = hook((uintptr_t)call_destructors_dlinfo->dli_saddr, (uintptr_t)sh_linker_proxy_soinfo_call_dtors, - (uintptr_t *)&sh_linker_orig_soinfo_call_dtors, &backup_len_dtors, call_destructors_dlinfo); + (uintptr_t *)&sh_linker_orig_soinfo_call_dtors, &backup_len_dtors, call_destructors_dlinfo, false); if (__predict_false(0 != r_hook_dtors)) { #if SH_LINKER_HOOK_WITH_DL_MUTEX pthread_mutex_unlock(g_dl_mutex); @@ -718,8 +718,9 @@ int sh_linker_unregister_dl_fini_callback(shadowhook_dl_info_t pre, shadowhook_d return 0; } -int sh_linker_get_dlinfo_by_addr(void *addr, xdl_info_t *dlinfo, char *lib_name, size_t lib_name_sz, - char *sym_name, size_t sym_name_sz, bool ignore_symbol_check) { +int sh_linker_get_dlinfo_by_addr(void *addr, xdl_info_t *dlinfo, bool ignore_symbol_check) { + memset(dlinfo, 0, sizeof(xdl_info_t)); + // dladdr() bool crashed = false; void *dlcache = NULL; @@ -777,9 +778,6 @@ int sh_linker_get_dlinfo_by_addr(void *addr, xdl_info_t *dlinfo, char *lib_name, r = SHADOWHOOK_ERRNO_HOOK_SYMSZ; goto end; } - - if (NULL != lib_name) strlcpy(lib_name, dlinfo->dli_fname, lib_name_sz); - if (NULL != sym_name) strlcpy(sym_name, dlinfo->dli_sname, sym_name_sz); r = 0; end: @@ -787,8 +785,9 @@ int sh_linker_get_dlinfo_by_addr(void *addr, xdl_info_t *dlinfo, char *lib_name, return r; } -int sh_linker_get_dlinfo_by_sym_name(const char *lib_name, const char *sym_name, xdl_info_t *dlinfo, - char *real_lib_name, size_t real_lib_name_sz) { +int sh_linker_get_dlinfo_by_sym_name(const char *lib_name, const char *sym_name, xdl_info_t *dlinfo) { + memset(dlinfo, 0, sizeof(xdl_info_t)); + // open library bool crashed = false; void *handle = NULL; @@ -839,6 +838,5 @@ int sh_linker_get_dlinfo_by_sym_name(const char *lib_name, const char *sym_name, dlinfo->dli_sname = sym_name; dlinfo->dli_saddr = addr; dlinfo->dli_ssize = sym_size; - if (NULL != real_lib_name) strlcpy(real_lib_name, dlinfo->dli_fname, real_lib_name_sz); return 0; } diff --git a/shadowhook/src/main/cpp/sh_linker.h b/shadowhook/src/main/cpp/sh_linker.h index 6c8745d..d1d9712 100644 --- a/shadowhook/src/main/cpp/sh_linker.h +++ b/shadowhook/src/main/cpp/sh_linker.h @@ -45,7 +45,5 @@ int sh_linker_register_dl_fini_callback(shadowhook_dl_info_t pre, shadowhook_dl_ int sh_linker_unregister_dl_fini_callback(shadowhook_dl_info_t pre, shadowhook_dl_info_t post, void *data); // linker utils -int sh_linker_get_dlinfo_by_addr(void *addr, xdl_info_t *dlinfo, char *lib_name, size_t lib_name_sz, - char *sym_name, size_t sym_name_sz, bool ignore_symbol_check); -int sh_linker_get_dlinfo_by_sym_name(const char *lib_name, const char *sym_name, xdl_info_t *dlinfo, - char *real_lib_name, size_t real_lib_name_sz); +int sh_linker_get_dlinfo_by_addr(void *addr, xdl_info_t *dlinfo, bool ignore_symbol_check); +int sh_linker_get_dlinfo_by_sym_name(const char *lib_name, const char *sym_name, xdl_info_t *dlinfo); diff --git a/shadowhook/src/main/cpp/sh_switch.c b/shadowhook/src/main/cpp/sh_switch.c index 3215875..d75a23d 100644 --- a/shadowhook/src/main/cpp/sh_switch.c +++ b/shadowhook/src/main/cpp/sh_switch.c @@ -124,7 +124,7 @@ static void sh_switch_dump_enter(sh_switch_t *self) { } static int sh_switch_hook_unique(uintptr_t target_addr, uintptr_t new_addr, uintptr_t *orig_addr, - size_t *backup_len, xdl_info_t *dlinfo) { + size_t *backup_len, xdl_info_t *dlinfo, bool ignore_symbol_check) { sh_switch_t *self = sh_switch_find(target_addr); if (NULL != self) return SHADOWHOOK_ERRNO_HOOK_DUP; @@ -148,7 +148,8 @@ static int sh_switch_hook_unique(uintptr_t target_addr, uintptr_t new_addr, uint (NULL != safe_orig_addr_addr && 0 == __atomic_load_n(safe_orig_addr_addr, __ATOMIC_ACQUIRE)) ? safe_orig_addr_addr : NULL; - if (0 != (r = sh_inst_hook(&self->inst, target_addr, dlinfo, new_addr, orig_addr, orig_addr2))) { + if (0 != (r = sh_inst_hook(&self->inst, target_addr, dlinfo, new_addr, orig_addr, orig_addr2, + ignore_symbol_check))) { RB_REMOVE(sh_switch_tree, &sh_switches, self); useless = self; goto end; @@ -163,7 +164,7 @@ static int sh_switch_hook_unique(uintptr_t target_addr, uintptr_t new_addr, uint } static int sh_switch_hook_shared(uintptr_t target_addr, uintptr_t new_addr, uintptr_t *orig_addr, - size_t *backup_len, xdl_info_t *dlinfo) { + size_t *backup_len, xdl_info_t *dlinfo, bool ignore_symbol_check) { int r; pthread_rwlock_rdlock(&sh_switches_lock); // SYNC(read) - start @@ -201,8 +202,9 @@ static int sh_switch_hook_shared(uintptr_t target_addr, uintptr_t new_addr, uint } else { // do hook uintptr_t *safe_orig_addr_addr = sh_safe_get_orig_addr_addr(target_addr); - if (0 != (r = sh_inst_hook(&self->inst, target_addr, dlinfo, hub_trampo, - sh_hub_get_orig_addr_addr(self->hub), safe_orig_addr_addr))) { + if (0 != + (r = sh_inst_hook(&self->inst, target_addr, dlinfo, hub_trampo, sh_hub_get_orig_addr_addr(self->hub), + safe_orig_addr_addr, ignore_symbol_check))) { RB_REMOVE(sh_switch_tree, &sh_switches, self); useless = self; goto end; @@ -231,12 +233,12 @@ static int sh_switch_hook_shared(uintptr_t target_addr, uintptr_t new_addr, uint } int sh_switch_hook(uintptr_t target_addr, uintptr_t new_addr, uintptr_t *orig_addr, size_t *backup_len, - xdl_info_t *dlinfo) { + xdl_info_t *dlinfo, bool ignore_symbol_check) { int r; if (SHADOWHOOK_IS_UNIQUE_MODE) - r = sh_switch_hook_unique(target_addr, new_addr, orig_addr, backup_len, dlinfo); + r = sh_switch_hook_unique(target_addr, new_addr, orig_addr, backup_len, dlinfo, ignore_symbol_check); else - r = sh_switch_hook_shared(target_addr, new_addr, orig_addr, backup_len, dlinfo); + r = sh_switch_hook_shared(target_addr, new_addr, orig_addr, backup_len, dlinfo, ignore_symbol_check); if (0 == r) SH_LOG_INFO("switch: hook in %s mode OK: target_addr %" PRIxPTR ", new_addr %" PRIxPTR, @@ -251,7 +253,7 @@ static int sh_switch_hook_unique_invisible(uintptr_t target_addr, uintptr_t new_ // do hook sh_inst_t inst; - int r = sh_inst_hook(&inst, target_addr, dlinfo, new_addr, orig_addr, NULL); + int r = sh_inst_hook(&inst, target_addr, dlinfo, new_addr, orig_addr, NULL, false); pthread_rwlock_unlock(&sh_switches_lock); // SYNC - end @@ -260,12 +262,14 @@ static int sh_switch_hook_unique_invisible(uintptr_t target_addr, uintptr_t new_ } int sh_switch_hook_invisible(uintptr_t target_addr, uintptr_t new_addr, uintptr_t *orig_addr, - size_t *backup_len, xdl_info_t *dlinfo) { + size_t *backup_len, xdl_info_t *dlinfo, bool ignore_symbol_check) { + (void)ignore_symbol_check; + int r; if (SHADOWHOOK_IS_UNIQUE_MODE) r = sh_switch_hook_unique_invisible(target_addr, new_addr, orig_addr, backup_len, dlinfo); else - r = sh_switch_hook_shared(target_addr, new_addr, orig_addr, backup_len, dlinfo); + r = sh_switch_hook_shared(target_addr, new_addr, orig_addr, backup_len, dlinfo, false); if (0 == r) SH_LOG_INFO("switch: hook(invisible) in %s mode OK: target_addr %" PRIxPTR ", new_addr %" PRIxPTR, diff --git a/shadowhook/src/main/cpp/sh_switch.h b/shadowhook/src/main/cpp/sh_switch.h index f9925ac..1adf9fc 100644 --- a/shadowhook/src/main/cpp/sh_switch.h +++ b/shadowhook/src/main/cpp/sh_switch.h @@ -22,15 +22,16 @@ // Created by Kelun Cai (caikelun@bytedance.com) on 2021-04-11. #pragma once +#include #include #include "xdl.h" int sh_switch_hook(uintptr_t target_addr, uintptr_t new_addr, uintptr_t *orig_addr, size_t *backup_len, - xdl_info_t *dlinfo); + xdl_info_t *dlinfo, bool ignore_symbol_check); int sh_switch_unhook(uintptr_t target_addr, uintptr_t new_addr); int sh_switch_hook_invisible(uintptr_t target_addr, uintptr_t new_addr, uintptr_t *orig_addr, - size_t *backup_len, xdl_info_t *dlinfo); + size_t *backup_len, xdl_info_t *dlinfo, bool ignore_symbol_check); void sh_switch_free_after_dlclose(xdl_info_t *dlinfo); diff --git a/shadowhook/src/main/cpp/sh_task.c b/shadowhook/src/main/cpp/sh_task.c index 100b947..88912b8 100644 --- a/shadowhook/src/main/cpp/sh_task.c +++ b/shadowhook/src/main/cpp/sh_task.c @@ -50,7 +50,7 @@ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wpadded" struct sh_task { - char *lib_name; // NULL means: hook_sym_addr or hook_func_addr + char *lib_name; char *sym_name; uintptr_t target_addr; uintptr_t new_addr; @@ -61,6 +61,7 @@ struct sh_task { bool finished; bool error; bool ignore_symbol_check; + bool hook_by_target_addr; TAILQ_ENTRY(sh_task, ) link; }; #pragma clang diagnostic pop @@ -88,6 +89,7 @@ sh_task_t *sh_task_create_by_target_addr(uintptr_t target_addr, uintptr_t new_ad self->finished = false; self->error = false; self->ignore_symbol_check = ignore_symbol_check; + self->hook_by_target_addr = true; return self; } @@ -109,6 +111,7 @@ sh_task_t *sh_task_create_by_sym_name(const char *lib_name, const char *sym_name self->finished = false; self->error = false; self->ignore_symbol_check = false; + self->hook_by_target_addr = false; return self; @@ -148,20 +151,17 @@ static int sh_task_hook_pending(struct dl_phdr_info *info, size_t size, void *ar } xdl_info_t dlinfo; - char real_lib_name[512]; - int r = sh_linker_get_dlinfo_by_sym_name(task->lib_name, task->sym_name, &dlinfo, real_lib_name, - sizeof(real_lib_name)); + int r = sh_linker_get_dlinfo_by_sym_name(task->lib_name, task->sym_name, &dlinfo); task->target_addr = (uintptr_t)dlinfo.dli_saddr; if (SHADOWHOOK_ERRNO_PENDING != r) { size_t backup_len = 0; if (0 == r) { - r = sh_switch_hook(task->target_addr, task->new_addr, task->orig_addr, &backup_len, &dlinfo); + r = sh_switch_hook(task->target_addr, task->new_addr, task->orig_addr, &backup_len, &dlinfo, false); if (0 != r) task->error = true; } else { - strlcpy(real_lib_name, task->lib_name, sizeof(real_lib_name)); task->error = true; } - sh_recorder_add_hook(r, false, task->target_addr, real_lib_name, task->sym_name, task->new_addr, + sh_recorder_add_hook(r, false, task->target_addr, task->lib_name, task->sym_name, task->new_addr, backup_len, (uintptr_t)task, task->caller_addr); task->finished = true; sh_task_do_callback(task, r); @@ -209,7 +209,7 @@ static void sh_task_dl_fini_post(struct dl_phdr_info *info, size_t size, void *d pthread_rwlock_rdlock(&sh_tasks_lock); sh_task_t *task; TAILQ_FOREACH(task, &sh_tasks, link) { - if (task->finished && task->lib_name != NULL && task->sym_name != NULL && 0 != task->target_addr && + if (task->finished && !task->hook_by_target_addr && 0 != task->target_addr && sh_util_is_in_elf_pt_load(dlinfo.dli_fbase, dlinfo.dlpi_phdr, dlinfo.dlpi_phnum, task->target_addr)) { task->target_addr = 0; task->error = false; @@ -255,20 +255,13 @@ int sh_task_init(void) { int sh_task_hook(sh_task_t *self) { int r; - bool is_hook_sym_addr = true; - char real_lib_name[512] = "unknown"; - char real_sym_name[1024] = "unknown"; size_t backup_len = 0; - - // find target-address by library-name and symbol-name xdl_info_t dlinfo; memset(&dlinfo, 0, sizeof(xdl_info_t)); - if (0 == self->target_addr) { - is_hook_sym_addr = false; - strlcpy(real_lib_name, self->lib_name, sizeof(real_lib_name)); - strlcpy(real_sym_name, self->sym_name, sizeof(real_sym_name)); - r = sh_linker_get_dlinfo_by_sym_name(self->lib_name, self->sym_name, &dlinfo, real_lib_name, - sizeof(real_lib_name)); + + // find target-address by library-name and symbol-name + if (!self->hook_by_target_addr) { + r = sh_linker_get_dlinfo_by_sym_name(self->lib_name, self->sym_name, &dlinfo); if (SHADOWHOOK_ERRNO_PENDING == r) { #if SH_UTIL_COMPATIBLE_WITH_ARM_ANDROID_4_X if (__predict_false(sh_util_get_api_level() < __ANDROID_API_L__)) { @@ -281,10 +274,6 @@ int sh_task_hook(sh_task_t *self) { } if (0 != r) goto end; // error self->target_addr = (uintptr_t)dlinfo.dli_saddr; // OK - } else { - r = sh_linker_get_dlinfo_by_addr((void *)self->target_addr, &dlinfo, real_lib_name, sizeof(real_lib_name), - real_sym_name, sizeof(real_sym_name), self->ignore_symbol_check); - if (0 != r) goto end; // error } // In Android 4.x with UNIQUE mode, if external users are hooking the linker's dlopen(), @@ -301,12 +290,12 @@ int sh_task_hook(sh_task_t *self) { #endif // hook by target-address - r = sh_switch_hook(self->target_addr, self->new_addr, self->orig_addr, &backup_len, &dlinfo); + r = sh_switch_hook(self->target_addr, self->new_addr, self->orig_addr, &backup_len, &dlinfo, + self->ignore_symbol_check); self->finished = true; end: - if (0 == r || SHADOWHOOK_ERRNO_PENDING == r) // "PENDING" is NOT an error - { + if (0 == r || SHADOWHOOK_ERRNO_PENDING == r /* "PENDING" is NOT an error */) { pthread_rwlock_wrlock(&sh_tasks_lock); TAILQ_INSERT_TAIL(&sh_tasks, self, link); if (!self->finished) __atomic_add_fetch(&sh_tasks_unfinished_cnt, 1, __ATOMIC_SEQ_CST); @@ -314,9 +303,10 @@ int sh_task_hook(sh_task_t *self) { } // record - sh_recorder_add_hook(r, is_hook_sym_addr, self->target_addr, real_lib_name, real_sym_name, self->new_addr, - backup_len, (uintptr_t)self, self->caller_addr); - + sh_recorder_add_hook(r, self->hook_by_target_addr, self->target_addr, + NULL != self->lib_name ? self->lib_name : "unknown", + NULL != self->sym_name ? self->sym_name : "unknown", self->new_addr, backup_len, + (uintptr_t)self, self->caller_addr); return r; }