19
19
*/
20
20
21
21
#include < dlfcn.h>
22
- #include " lsplt.hpp"
23
22
#include < sys/mman.h>
23
+
24
+ #include " elf_util.h"
25
+ #include " lsplt.hpp"
26
+ #include " symbol_cache.h"
24
27
#pragma clang diagnostic push
25
28
#pragma clang diagnostic ignored "-Wunused-value"
26
29
#pragma once
27
30
28
31
#include < context.h>
29
- #include " utils/jni_helper.hpp"
30
- #include " logging.h"
31
- #include " config.h"
32
+
32
33
#include < cassert>
34
+
35
+ #include " ../src/native_api.h"
36
+ #include " config.h"
33
37
#include " config_bridge.h"
38
+ #include " logging.h"
39
+ #include " utils/jni_helper.hpp"
34
40
35
41
namespace lspd {
36
42
37
43
[[gnu::always_inline]]
38
- inline bool RegisterNativeMethodsInternal (JNIEnv *env,
39
- std::string_view class_name,
40
- const JNINativeMethod *methods,
41
- jint method_count) {
42
-
44
+ inline bool RegisterNativeMethodsInternal (JNIEnv *env, std::string_view class_name,
45
+ const JNINativeMethod *methods, jint method_count) {
43
46
auto clazz = Context::GetInstance ()->FindClassFromCurrentLoader (env, class_name.data ());
44
47
if (clazz.get () == nullptr ) {
45
48
LOGF (" Couldn't find class: {}" , class_name.data ());
@@ -49,83 +52,70 @@ inline bool RegisterNativeMethodsInternal(JNIEnv *env,
49
52
}
50
53
51
54
#if defined(__cplusplus)
52
- #define _NATIVEHELPER_JNI_MACRO_CAST (to ) \
53
- reinterpret_cast <to>
55
+ #define _NATIVEHELPER_JNI_MACRO_CAST (to ) reinterpret_cast <to>
54
56
#else
55
- #define _NATIVEHELPER_JNI_MACRO_CAST (to ) \
56
- (to)
57
+ #define _NATIVEHELPER_JNI_MACRO_CAST (to ) (to)
57
58
#endif
58
59
59
60
#ifndef LSP_NATIVE_METHOD
60
- #define LSP_NATIVE_METHOD (className, functionName, signature ) \
61
- { #functionName, \
62
- signature, \
63
- _NATIVEHELPER_JNI_MACRO_CAST (void *) (Java_org_lsposed_lspd_nativebridge_## className ## _ ## functionName) \
64
- }
61
+ #define LSP_NATIVE_METHOD (className, functionName, signature ) \
62
+ {#functionName, signature, \
63
+ _NATIVEHELPER_JNI_MACRO_CAST (void *)( \
64
+ Java_org_lsposed_lspd_nativebridge_##className##_##functionName)}
65
65
#endif
66
66
67
- #define JNI_START [[maybe_unused]] JNIEnv* env, [[maybe_unused]] jclass clazz
67
+ #define JNI_START [[maybe_unused]] JNIEnv * env, [[maybe_unused]] jclass clazz
68
68
69
69
#ifndef LSP_DEF_NATIVE_METHOD
70
- #define LSP_DEF_NATIVE_METHOD (ret, className, functionName, ...) \
71
- extern " C" ret Java_org_lsposed_lspd_nativebridge_## className ## _ ## functionName (JNI_START, ## __VA_ARGS__)
70
+ #define LSP_DEF_NATIVE_METHOD (ret, className, functionName, ...) \
71
+ extern " C" ret Java_org_lsposed_lspd_nativebridge_##className##_##functionName(JNI_START, \
72
+ ##__VA_ARGS__)
72
73
#endif
73
74
74
- #define REGISTER_LSP_NATIVE_METHODS (class_name ) \
75
- RegisterNativeMethodsInternal (env, GetNativeBridgeSignature() + #class_name, gMethods , arraysize(gMethods ))
76
-
77
- static std::vector<std::tuple<dev_t , ino_t , const char *, void **>> plt_hook_list = {};
78
- static auto scan_maps = lsplt::MapInfo::Scan();
79
-
80
- inline int plt_hook (const char *lib, const char *symbol, void *callback, void **backup) {
81
- dev_t dev = 0 ;
82
- ino_t inode = 0 ;
83
- for (auto map : scan_maps) {
84
- if (map.path == lib) {
85
- inode = map.inode ;
86
- dev = map.dev ;
87
- break ;
75
+ #define REGISTER_LSP_NATIVE_METHODS (class_name ) \
76
+ RegisterNativeMethodsInternal (env, GetNativeBridgeSignature() + #class_name, gMethods , \
77
+ arraysize (gMethods ))
78
+
79
+ static dev_t dev = 0 ;
80
+ static ino_t inode = 0 ;
81
+ static std::vector<std::pair<std::string_view, void **>> plt_hook_saved = {};
82
+
83
+ inline int HookArtFunction (void *original, void *callback, void **backup, bool save = true ) {
84
+ auto symbol = *reinterpret_cast <std::string_view *>(original);
85
+ if (dev == 0 || inode == 0 ) {
86
+ auto libart_path = GetArt ()->name ();
87
+ for (auto map : lsplt::MapInfo::Scan ()) {
88
+ if (map.path == libart_path) {
89
+ inode = map.inode ;
90
+ dev = map.dev ;
91
+ break ;
92
+ }
88
93
}
89
94
}
90
95
91
96
auto result = lsplt::RegisterHook (dev, inode, symbol, callback, backup) && lsplt::CommitHook ();
92
- if (result) {
93
- plt_hook_list.emplace_back (dev, inode, symbol, backup);
94
- return 0 ;
97
+ if (result && *backup != nullptr ) {
98
+ if (save) plt_hook_saved.emplace_back (symbol, backup);
99
+ } else if (auto addr = GetArt ()->getSymbAddress (symbol); addr) {
100
+ Dl_info info;
101
+ if (dladdr (addr, &info) && info.dli_sname != nullptr && info.dli_sname == symbol)
102
+ HookFunction (addr, callback, backup);
103
+ } else if (*backup == nullptr && isDebug) {
104
+ LOGW (" Failed to {} Art symbol {}" , save ? " hook" : " unhook" , symbol);
95
105
}
96
- return 1 ;
106
+ return *backup == nullptr ;
97
107
}
98
108
99
- inline int HookFunction (void *original, void *replace, void **backup) {
100
- Dl_info info;
101
- if (dladdr (original, &info)) {
102
- if constexpr (isDebug) {
103
- LOGD (" Hooking {} ({}) from {} ({})" ,
104
- info.dli_sname ? info.dli_sname : " (unknown symbol)" , info.dli_saddr ,
105
- info.dli_fname ? info.dli_fname : " (unknown file)" , info.dli_fbase );
106
- }
107
- if (info.dli_sname != NULL && info.dli_fname != NULL )
108
- return plt_hook (info.dli_fname , info.dli_sname , replace, backup);
109
- }
110
- return 1 ;
111
- }
112
-
113
- inline int UnhookFunction (void *original) {
114
- Dl_info info;
115
- if (dladdr (original, &info)) {
116
- if constexpr (isDebug) {
117
- LOGD (" Unhooking {} ({}) from {} ({})" ,
118
- info.dli_sname ? info.dli_sname : " (unknown symbol)" , info.dli_saddr ,
119
- info.dli_fname ? info.dli_fname : " (unknown file)" , info.dli_fbase );
120
- }
109
+ inline int UnhookArtFunction (void *original) {
110
+ std::string_view func_name = *reinterpret_cast <std::string_view *>(original);
111
+ auto hook_iter = std::find_if (plt_hook_saved.begin (), plt_hook_saved.end (),
112
+ [func_name](auto record) { return record.first == func_name; });
121
113
122
- for (const auto [dev, inode, symbol, backup] : plt_hook_list) {
123
- if (info.dli_sname == symbol) {
124
- auto result = lsplt::RegisterHook (dev, inode, symbol, backup, nullptr )
125
- && lsplt::CommitHook ();
126
- return 1 - result;
127
- }
128
- }
114
+ void *stub = nullptr ;
115
+ if (hook_iter != plt_hook_saved.end () &&
116
+ HookArtFunction (original, *(hook_iter->second ), &stub, false )) {
117
+ plt_hook_saved.erase (hook_iter);
118
+ return 0 ;
129
119
}
130
120
return 1 ;
131
121
}
@@ -136,6 +126,6 @@ inline std::string GetNativeBridgeSignature() {
136
126
return signature;
137
127
}
138
128
139
- } // namespace lspd
129
+ } // namespace lspd
140
130
141
131
#pragma clang diagnostic pop
0 commit comments