1 /*
2 The hook mode has 3 kinds which can be set by command "param set":
3 (1) param set libc.hook_mode "startup:\"prog1 \""
4 (2) param set libc.hook_mode startup:program1
5 (3) param set libc.hook_mode step
6 (4) param set libc.hook_mode direct
7
8 Case 1 represents "startup" mode, and the hooked process is "prog1 ",
9 which loads hooking shared library when the program starts up.
10 The path is added with two quotation marks because a quotation mark is a special charcter,
11 which need be escaped.
12 (2) is similar with (1), but no escaped character, so quotation marks doesn't need.
13 (3) represents "step" mode, which loads hooking shared library by some steps.
14 (4) represetnt "direct" mode, which loads hooking shared library by a step.
15 */
16
17 #ifdef HOOK_ENABLE
18 #include <unistd.h>
19 #include <signal.h>
20 #include "musl_malloc_dispatch_table.h"
21 #include "musl_malloc.h"
22 #include "musl_preinit_common.h"
23 #ifdef OHOS_ENABLE_PARAMETER
24 #include "sys_param.h"
25 #endif
26 #include <pthread.h>
27 #include <stdlib.h>
28 #include <limits.h>
29 #include <dlfcn.h>
30 #include <errno.h>
31 #include <stdatomic.h>
32 #include <ctype.h>
33 #include <assert.h>
34 #include <string.h>
35 #include <malloc.h>
36 #include "musl_log.h"
37
38 void* ohos_malloc_hook_init_function(size_t bytes);
default_memtrace(void * addr,size_t size,const char * tag,bool is_using)39 void default_memtrace(void* addr, size_t size, const char* tag, bool is_using) {}
40
41 static struct MallocDispatchType __ohos_malloc_hook_init_dispatch = {
42 .malloc = ohos_malloc_hook_init_function,
43 .free = MuslFunc(free),
44 .mmap = MuslMalloc(mmap),
45 .munmap = MuslMalloc(munmap),
46 .calloc = MuslFunc(calloc),
47 .realloc = MuslFunc(realloc),
48 .prctl = MuslMalloc(prctl),
49 .malloc_usable_size = MuslMalloc(malloc_usable_size),
50 .memtrace = default_memtrace,
51 .aligned_alloc = MuslMalloc(aligned_alloc),
52 };
53 #define MAX_SYM_NAME_SIZE 1000
54 #define MAX_PROC_NAME_SIZE 256
55 #define ADDR_NATIVE_ENABLE (1<<4)
56 #define ADDR_NATIVE_DISABLE (1<<5)
57 #define ADDR_NATIVE_SAVE (1<<6)
58 #define ADDR_NATIVE_CLEAR (1<<7)
59 static char *__malloc_hook_shared_lib = "libnative_hook.z.so";
60 static char *__malloc_hook_function_prefix = "ohos_malloc_hook";
61 volatile atomic_llong ohos_malloc_hook_shared_library;
62 static char *kMemTrackSharedLib = "libmemleak_tracker.so";
63 static char *kMemTrackPrefix = "track";
64 static char *kMemTrackPropertyEnable = "const.hiview.memleak_tracker.enable";
65 static char *kMemTrackSign = "true";
66 bool checkLoadMallocMemTrack = false;
67 unsigned int memLeakTypeContent = 0;
68 volatile atomic_llong memleak_ever_shared_library_handle;
69 volatile atomic_llong ohos_malloc_ever_shared_library_handle;
70 void* function_of_shared_lib[LAST_FUNCTION];
71 void* function_of_ohos_malloc_shared_lib[LAST_FUNCTION];
72 void* function_of_memleak_shared_lib[LAST_FUNCTION];
73 static enum EnumHookMode __hook_mode = STEP_HOOK_MODE;
74 static void __uninstal_malloc_hook();
75
get_native_hook_param(char * buf,unsigned int buf_len)76 static void get_native_hook_param(char *buf, unsigned int buf_len)
77 {
78 #ifdef OHOS_ENABLE_PARAMETER
79 CachedHandle handle = CachedParameterCreate(MUSL_HOOK_PARAM_NAME, "");
80 const char *value = CachedParameterGet(handle);
81 if (value != NULL) {
82 size_t size = strlen(value);
83 if (size > 0 && size < buf_len) {
84 strcpy(buf, value);
85 }
86 }
87 CachedParameterDestroy(handle);
88 #else
89 return;
90 #endif
91 }
92
get_memleak_hook_param()93 static void get_memleak_hook_param()
94 {
95 #ifdef OHOS_ENABLE_PARAMETER
96 CachedHandle handle = CachedParameterCreate(kMemTrackPropertyEnable, "false");
97 const char *value = CachedParameterGet(handle);
98 if (value != NULL && strncmp(value, kMemTrackSign, strlen(kMemTrackSign)) == 0) {
99 checkLoadMallocMemTrack = true;
100 }
101 CachedParameterDestroy(handle);
102 #else
103 return;
104 #endif
105 }
106
parse_hook_variable(enum EnumHookMode * mode,char * path,int size)107 static int parse_hook_variable(enum EnumHookMode* mode, char* path, int size)
108 {
109 if (!mode || !path || size <= 0) {
110 return -1;
111 }
112 char hook_param_value[OHOS_PARAM_MAX_SIZE + 1] = {0};
113 unsigned int len = OHOS_PARAM_MAX_SIZE;
114 get_native_hook_param(hook_param_value, len);
115 if (hook_param_value[0] == '\0') {
116 *mode = STEP_HOOK_MODE;
117 path[0] = '\0';
118 } else {
119 char* ptr = hook_param_value;
120 while (*ptr && *ptr != ':') {
121 ++ptr;
122 }
123
124 if (*ptr == ':') {
125 *ptr = '\0';
126 ++ptr;
127 }
128
129 if (strcmp(hook_param_value, "startup") == 0) {
130 *mode = STARTUP_HOOK_MODE;
131 } else if (strcmp(hook_param_value, "direct") == 0) {
132 *mode = DIRECT_HOOK_MODE;
133 } else if (strcmp(hook_param_value, "step") == 0) {
134 *mode = STEP_HOOK_MODE;
135 } else {
136 *mode = STEP_HOOK_MODE;
137 }
138 if (*mode == STARTUP_HOOK_MODE) {
139 if (*ptr == '\"') {
140 ++ptr;
141 int idx = 0;
142 while (idx < size - 1 && *ptr && *ptr != '\"') {
143 path[idx++] = *ptr++;
144 }
145 path[idx] = '\0';
146 } else {
147 int idx = 0;
148 while (idx < size - 1 && *ptr) {
149 path[idx++] = *ptr++;
150 }
151 path[idx] = '\0';
152 }
153 }
154 }
155 return 0;
156 }
157
get_proc_name(pid_t pid,char * buf,unsigned int buf_len)158 static bool get_proc_name(pid_t pid, char *buf, unsigned int buf_len)
159 {
160 if (pid <= 0) {
161 return false;
162 }
163 char target_file[FILE_NAME_MAX_SIZE] = {0};
164 (void)snprintf(target_file, sizeof(target_file), "/proc/%d/cmdline", pid);
165 FILE *f = fopen(target_file, "r");
166 if (f == NULL) {
167 return false;
168 }
169 if (fgets(buf, buf_len, f) == NULL) {
170 (void)fclose(f);
171 return false;
172 }
173 (void)fclose(f);
174 return true;
175 }
176
init_malloc_function(void * malloc_shared_library_handler,MallocMallocType * func,const char * prefix)177 static bool init_malloc_function(void* malloc_shared_library_handler, MallocMallocType* func, const char* prefix)
178 {
179 char symbol[MAX_SYM_NAME_SIZE];
180 snprintf(symbol, sizeof(symbol), "%s_%s", prefix, "malloc");
181 *func = (MallocMallocType)(dlsym(malloc_shared_library_handler, symbol));
182 if (*func == NULL) {
183 return false;
184 }
185 return true;
186 }
187
init_free_function(void * malloc_shared_library_handler,MallocFreeType * func,const char * prefix)188 static bool init_free_function(void* malloc_shared_library_handler, MallocFreeType* func, const char* prefix)
189 {
190 char symbol[MAX_SYM_NAME_SIZE];
191 snprintf(symbol, sizeof(symbol), "%s_%s", prefix, "free");
192 *func = (MallocFreeType)(dlsym(malloc_shared_library_handler, symbol));
193 if (*func == NULL) {
194 return false;
195 }
196 return true;
197 }
198
init_mmap_function(void * malloc_shared_library_handler,MallocMmapType * func,const char * prefix)199 static bool init_mmap_function(void* malloc_shared_library_handler, MallocMmapType* func, const char* prefix)
200 {
201 char symbol[MAX_SYM_NAME_SIZE];
202 snprintf(symbol, sizeof(symbol), "%s_%s", prefix, "mmap");
203 *func = (MallocMmapType)(dlsym(malloc_shared_library_handler, symbol));
204 if (*func == NULL) {
205 return false;
206 }
207 return true;
208 }
209
init_munmap_function(void * malloc_shared_library_handler,MallocMunmapType * func,const char * prefix)210 static bool init_munmap_function(void* malloc_shared_library_handler, MallocMunmapType* func, const char* prefix)
211 {
212 char symbol[MAX_SYM_NAME_SIZE];
213 snprintf(symbol, sizeof(symbol), "%s_%s", prefix, "munmap");
214 *func = (MallocMunmapType)(dlsym(malloc_shared_library_handler, symbol));
215 if (*func == NULL) {
216 return false;
217 }
218 return true;
219 }
220
init_memtrace_function(void * malloc_shared_library_handler,MemTrace * func,const char * prefix)221 static bool init_memtrace_function(void* malloc_shared_library_handler, MemTrace* func, const char* prefix)
222 {
223 char symbol[MAX_SYM_NAME_SIZE];
224 snprintf(symbol, sizeof(symbol), "%s_%s", prefix, "memtrace");
225 *func = (MemTrace)(dlsym(malloc_shared_library_handler, symbol));
226 if (*func == NULL) {
227 return false;
228 }
229 return true;
230 }
231
init_calloc_function(void * malloc_shared_library_handler,MallocCallocType * func,const char * prefix)232 static bool init_calloc_function(void* malloc_shared_library_handler, MallocCallocType* func, const char* prefix)
233 {
234 char symbol[MAX_SYM_NAME_SIZE];
235 snprintf(symbol, sizeof(symbol), "%s_%s", prefix, "calloc");
236 *func = (MallocCallocType)(dlsym(malloc_shared_library_handler, symbol));
237 if (*func == NULL) {
238 return false;
239 }
240 return true;
241 }
242
init_realloc_function(void * malloc_shared_library_handler,MallocReallocType * func,const char * prefix)243 static bool init_realloc_function(void* malloc_shared_library_handler, MallocReallocType* func, const char* prefix)
244 {
245 char symbol[MAX_SYM_NAME_SIZE];
246 snprintf(symbol, sizeof(symbol), "%s_%s", prefix, "realloc");
247 *func = (MallocReallocType)(dlsym(malloc_shared_library_handler, symbol));
248 if (*func == NULL) {
249 return false;
250 }
251 return true;
252 }
253
init_malloc_usable_size_function(void * malloc_shared_library_handler,MallocMallocUsableSizeType * func,const char * prefix)254 static bool init_malloc_usable_size_function(void* malloc_shared_library_handler, MallocMallocUsableSizeType* func, const char* prefix)
255 {
256 char symbol[MAX_SYM_NAME_SIZE];
257 snprintf(symbol, sizeof(symbol), "%s_%s", prefix, "malloc_usable_size");
258 *func = (MallocMallocUsableSizeType)(dlsym(malloc_shared_library_handler, symbol));
259 if (*func == NULL) {
260 return false;
261 }
262 return true;
263 }
264
init_prctl_function(void * malloc_shared_library_handler,MallocPrctlType * func,const char * prefix)265 static bool init_prctl_function(void* malloc_shared_library_handler, MallocPrctlType* func, const char* prefix)
266 {
267 char symbol[MAX_SYM_NAME_SIZE];
268 snprintf(symbol, sizeof(symbol), "%s_%s", prefix, "prctl");
269 *func = (MallocPrctlType)(dlsym(malloc_shared_library_handler, symbol));
270 if (*func == NULL) {
271 return false;
272 }
273 return true;
274 }
275
init_aligned_alloc_function(void * malloc_shared_library_handler,MallocAlignedAllocType * func,const char * prefix)276 static bool init_aligned_alloc_function(void* malloc_shared_library_handler, MallocAlignedAllocType* func, const char* prefix)
277 {
278 char symbol[MAX_SYM_NAME_SIZE];
279 snprintf(symbol, sizeof(symbol), "%s_%s", prefix, "aligned_alloc");
280 *func = (MallocAlignedAllocType)(dlsym(malloc_shared_library_handler, symbol));
281 if (*func == NULL) {
282 return false;
283 }
284 return true;
285 }
286
287 #ifdef USE_JEMALLOC_RECYCLE_FUNC
288 extern int je_reclaim_cache();
handle_recycle_cache()289 static void handle_recycle_cache()
290 {
291 int ret;
292 MUSL_LOGD("je_reclaim_cache begin.");
293 ret = je_reclaim_cache();
294 MUSL_LOGD("je_reclaim_cache result=%{public}d.", ret);
295 }
296
init_jemalloc_recycle_handler()297 static void init_jemalloc_recycle_handler()
298 {
299 struct sigaction action = {};
300 action.sa_handler = NULL;
301 action.sa_sigaction = handle_recycle_cache;
302 sigemptyset(&action.sa_mask);
303 sigaddset(&action.sa_mask, MUSL_SIGNAL_RECYCLE_JEMALLOC);
304 action.sa_flags = SA_SIGINFO | SA_RESTART;
305 action.sa_restorer = NULL;
306 sigaction(MUSL_SIGNAL_RECYCLE_JEMALLOC, &action, NULL);
307 }
308 #endif
309
init_hook_functions(void * shared_library_handler,struct MallocDispatchType * table,const char * prefix)310 static bool init_hook_functions(void* shared_library_handler, struct MallocDispatchType* table, const char* prefix)
311 {
312 if (!init_malloc_function(shared_library_handler, &table->malloc, prefix)) {
313 return false;
314 }
315 if (!init_free_function(shared_library_handler, &table->free, prefix)) {
316 return false;
317 }
318 if (!init_mmap_function(shared_library_handler, &table->mmap, prefix)) {
319 return false;
320 }
321 if (!init_munmap_function(shared_library_handler, &table->munmap, prefix)) {
322 return false;
323 }
324 if (!init_calloc_function(shared_library_handler, &table->calloc, prefix)) {
325 return false;
326 }
327 if (!init_realloc_function(shared_library_handler, &table->realloc, prefix)) {
328 return false;
329 }
330 if (!init_memtrace_function(shared_library_handler, &table->memtrace, prefix)) {
331 return false;
332 }
333 if (!init_malloc_usable_size_function(shared_library_handler, &table->malloc_usable_size, prefix)) {
334 return false;
335 }
336 if (!init_prctl_function(shared_library_handler, &table->prctl, prefix)) {
337 return false;
338 }
339 if (!init_aligned_alloc_function(shared_library_handler, &table->aligned_alloc, prefix)) {
340 return false;
341 }
342 return true;
343 }
344
clear_function_table()345 static void clear_function_table()
346 {
347 for (size_t i = 0; i < LAST_FUNCTION; i++) {
348 function_of_shared_lib[i] = NULL;
349 if (__get_memleak_hook_flag()) {
350 function_of_memleak_shared_lib[i] = NULL;
351 } else if (__get_global_hook_flag()) {
352 function_of_ohos_malloc_shared_lib[i] = NULL;
353 }
354 }
355 }
356
init_malloc_hook_shared_library(void * shared_library_handle,const char * shared_lib,const char * prefix,struct MallocDispatchType * dispatch_table)357 bool init_malloc_hook_shared_library(void* shared_library_handle, const char* shared_lib, const char* prefix, struct MallocDispatchType* dispatch_table)
358 {
359 static const char* names[] = {
360 "initialize",
361 "finalize",
362 "get_hook_flag",
363 "set_hook_flag",
364 "on_start",
365 "on_end",
366 "send_hook_misc_data",
367 "get_hook_config",
368 };
369
370 for (int i = 0; i < LAST_FUNCTION; i++) {
371 char symbol[MAX_SYM_NAME_SIZE];
372 snprintf(symbol, sizeof(symbol), "%s_%s", prefix, names[i]);
373 function_of_shared_lib[i] = dlsym(shared_library_handle, symbol);
374 if (__get_memleak_hook_flag()) {
375 function_of_memleak_shared_lib[i] = function_of_shared_lib[i];
376 } else if (__get_global_hook_flag()) {
377 function_of_ohos_malloc_shared_lib[i] = function_of_shared_lib[i];
378 }
379 if (function_of_shared_lib[i] == NULL) {
380 // __musl_log(__MUSL_LOG_ERROR, "%s: %s routine not found in %s\n", getprogname(), symbol, shared_lib);
381 clear_function_table();
382 return false;
383 }
384 }
385
386 if (!init_hook_functions(shared_library_handle, dispatch_table, prefix)) {
387 clear_function_table();
388 return false;
389 }
390
391 return true;
392 }
393
load_malloc_hook_shared_library(const char * shared_lib,const char * prefix,struct MallocDispatchType * dispatch_table)394 void* load_malloc_hook_shared_library(const char* shared_lib, const char* prefix, struct MallocDispatchType* dispatch_table)
395 {
396 void* shared_library_handle = NULL;
397
398 shared_library_handle = dlopen(shared_lib, RTLD_NOW | RTLD_LOCAL);
399
400 if (shared_library_handle == NULL) {
401 MUSL_LOGI("HiProfiler, Unable to open shared library %{public}s: %{public}s.", shared_lib, dlerror());
402 return NULL;
403 }
404
405 if (!init_malloc_hook_shared_library(shared_library_handle, shared_lib, prefix, dispatch_table)) {
406 dlclose(shared_library_handle);
407 shared_library_handle = NULL;
408 }
409 MUSL_LOGI("HiProfiler, load_malloc_hook_shared_library success.");
410 return shared_library_handle;
411 }
412
413 typedef void (*finalize_func_t)();
414 typedef bool (*init_func_t)(const struct MallocDispatchType*, bool*, const char*);
415 typedef bool (*on_start_func_t)();
416 typedef bool (*on_end_func_t)();
417
malloc_finalize()418 static void malloc_finalize()
419 {
420 __set_hook_flag(false);
421 ((finalize_func_t)function_of_shared_lib[FINALIZE_FUNCTION])();
422
423 fclose(stdin);
424 fclose(stdout);
425 fclose(stderr);
426 }
427
finish_install_ohos_malloc_hooks(struct musl_libc_globals * globals,const char * options,const char * prefix,void * shared_library_handle)428 bool finish_install_ohos_malloc_hooks(struct musl_libc_globals* globals, const char* options, const char* prefix, void* shared_library_handle)
429 {
430 init_func_t init_func = (init_func_t)(function_of_shared_lib[INITIALIZE_FUNCTION]);
431 if (!init_func(&__libc_malloc_default_dispatch, NULL, options)) {
432 // __musl_log(__MUSL_LOG_ERROR, "%s: failed to enable malloc %s\n", getprogname(), prefix);
433 clear_function_table();
434 return false;
435 }
436 on_start_func_t start_func = (on_start_func_t)(function_of_shared_lib[ON_START_FUNCTION]);
437 if (__get_global_hook_flag()) {
438 if (!start_func(__uninstal_malloc_hook)) {
439 // __musl_log(__MUSL_LOG_ERROR, "%s: failed to start %s\n", getprogname(), prefix);
440 clear_function_table();
441 return false;
442 }
443 atomic_store_explicit(&ohos_malloc_hook_shared_library, (volatile long long)shared_library_handle, memory_order_seq_cst);
444 atomic_store_explicit(&__musl_libc_globals.so_dispatch_table, (volatile long long)&globals->malloc_dispatch_table, memory_order_seq_cst);
445 atomic_store_explicit(&__musl_libc_globals.current_dispatch_table, (volatile long long)&globals->malloc_dispatch_table, memory_order_seq_cst);
446 }
447 if (__get_memleak_hook_flag() && checkLoadMallocMemTrack) {
448 if (!start_func(memLeakTypeContent)) {
449 clear_function_table();
450 return false;
451 }
452 atomic_store_explicit(&__musl_libc_globals.memleak_tracker_so_dispatch_table, (volatile long long)&globals->memleak_tracker_malloc_dispatch_table, memory_order_seq_cst);
453 atomic_store_explicit(&__musl_libc_globals.current_dispatch_table, (volatile long long)&globals->memleak_tracker_malloc_dispatch_table, memory_order_seq_cst);
454 }
455 int ret_value = atexit(malloc_finalize);
456 if (ret_value != 0) {
457 // __musl_log(__MUSL_LOG_ERROR, "failed to set atexit cleanup function: %d\n", ret_value);
458 }
459 return true;
460 }
461
is_empty_string(const char * str)462 static bool is_empty_string(const char* str)
463 {
464 while (*str) {
465 if (!isspace((unsigned char)(*str))) {
466 return false;
467 }
468 }
469 return true;
470 }
471
install_ohos_malloc_hook(struct musl_libc_globals * globals,const char * shared_lib,const char * prefix)472 static void install_ohos_malloc_hook(struct musl_libc_globals* globals, const char* shared_lib, const char* prefix)
473 {
474 volatile void* shared_library_handle = (volatile void *)atomic_load_explicit(&ohos_malloc_hook_shared_library, memory_order_acquire);
475 assert(shared_library_handle == NULL || shared_library_handle == (volatile void*)-1);
476 if (__get_memleak_hook_flag()) {
477 shared_library_handle = (volatile void*)load_malloc_hook_shared_library(shared_lib, prefix, &globals->memleak_tracker_malloc_dispatch_table);
478 } else if (__get_global_hook_flag()) {
479 shared_library_handle = (volatile void*)load_malloc_hook_shared_library(shared_lib, prefix, &globals->malloc_dispatch_table);
480 }
481 if (shared_library_handle == NULL) {
482 // __musl_log(__MUSL_LOG_ERROR, "Can't load shared library '%s'\n", __malloc_hook_shared_lib);
483 return;
484 }
485
486 if (finish_install_ohos_malloc_hooks(globals, NULL, prefix, shared_library_handle)) {
487 if (strncmp(__malloc_hook_function_prefix, prefix, strlen(prefix)) == 0) {
488 atomic_store_explicit(&ohos_malloc_ever_shared_library_handle, (volatile long long)shared_library_handle, memory_order_seq_cst);
489 } else {
490 atomic_store_explicit(&memleak_ever_shared_library_handle, (volatile long long)shared_library_handle, memory_order_seq_cst);
491 }
492 } else {
493 // __musl_log(__MUSL_LOG_ERROR, "finish_install_ohos_malloc_hooks failed\n");
494 dlclose((void *)shared_library_handle);
495 atomic_store_explicit(&ohos_malloc_hook_shared_library, (volatile long long)0, memory_order_seq_cst);
496 }
497 }
498
init_ohos_malloc_hook()499 static void* init_ohos_malloc_hook()
500 {
501 if (__get_memleak_hook_flag()) {
502 get_memleak_hook_param();
503 if (checkLoadMallocMemTrack) {
504 install_ohos_malloc_hook(&__musl_libc_globals, kMemTrackSharedLib, kMemTrackPrefix);
505 }
506 }
507 if (__get_global_hook_flag()) {
508 install_ohos_malloc_hook(&__musl_libc_globals, __malloc_hook_shared_lib, __malloc_hook_function_prefix);
509 }
510 return NULL;
511 }
512
ohos_malloc_hook_init_function(size_t bytes)513 void* ohos_malloc_hook_init_function(size_t bytes)
514 {
515 if (atomic_exchange(&__musl_libc_globals.current_dispatch_table, (volatile const long long)NULL)) {
516 pthread_t thread_id;
517 MUSL_LOGI("HiProfiler, ohos_malloc_hook_init_function, pthread_create.");
518 if (pthread_create(&thread_id, NULL, init_ohos_malloc_hook, NULL) != 0) {
519 // __musl_log(__MUSL_LOG_ERROR, "%s: ohos_malloc_hook: failed to pthread_create\n", getprogname());
520 } else if (pthread_detach(thread_id) != 0) {
521 // __musl_log(__MUSL_LOG_ERROR, "%s: ohos_malloc_hook: failed to pthread_detach\n", getprogname());
522 }
523 }
524 void*ptr = MuslFunc(malloc)(bytes);
525 return ptr;
526
527 }
528
__set_default_malloc()529 static void __set_default_malloc()
530 {
531 atomic_store_explicit(&__musl_libc_globals.current_dispatch_table, (volatile const long long)NULL, memory_order_seq_cst);
532 }
533
__restore_hook_function_table()534 static void __restore_hook_function_table()
535 {
536 for (size_t i = 0; i < LAST_FUNCTION; i++) {
537 if (__get_memleak_hook_flag()) {
538 function_of_shared_lib[i] = function_of_memleak_shared_lib[i];
539 } else if (__get_global_hook_flag()) {
540 function_of_shared_lib[i] = function_of_ohos_malloc_shared_lib[i];
541 }
542 }
543 }
544
__install_malloc_hook()545 static void __install_malloc_hook()
546 {
547 if (__get_memleak_hook_flag()) {
548 return;
549 }
550 atomic_store_explicit(&__hook_enable_hook_flag, (volatile bool)true, memory_order_seq_cst);
551 volatile void* ohos_malloc_ever_handle = (volatile void* )atomic_load_explicit(&ohos_malloc_ever_shared_library_handle, memory_order_acquire);
552 if (ohos_malloc_ever_handle != NULL) {
553 atomic_store_explicit(&ohos_malloc_hook_shared_library, (volatile long long)ohos_malloc_ever_handle, memory_order_seq_cst);
554 } else {
555 atomic_store_explicit(&ohos_malloc_hook_shared_library, (volatile long long)0, memory_order_seq_cst);
556 }
557 volatile void* shared_library_handle = (volatile void* )atomic_load_explicit(&ohos_malloc_hook_shared_library, memory_order_acquire);
558 if (shared_library_handle == NULL) {
559 MUSL_LOGI("HiProfiler, __install_malloc_hook __hook_mode %{public}d", __hook_mode);
560 if (__hook_mode == STEP_HOOK_MODE) {
561 atomic_store_explicit(&__musl_libc_globals.current_dispatch_table, (volatile const long long)&__ohos_malloc_hook_init_dispatch, memory_order_seq_cst);
562 atomic_store_explicit(&ohos_malloc_hook_shared_library, (volatile long long)-1, memory_order_seq_cst);
563 } else {
564 init_ohos_malloc_hook();
565 }
566 } else if (shared_library_handle != (void*)-1) {
567 __restore_hook_function_table();
568 on_start_func_t start_func = (on_start_func_t)(function_of_shared_lib[ON_START_FUNCTION]);
569 if (start_func && !start_func(__uninstal_malloc_hook)) {
570 // __musl_log(__MUSL_LOG_ERROR, "%s: failed to enable malloc\n", getprogname());
571 }
572 volatile const struct MallocDispatchType* so_dispatch_value = (volatile const struct MallocDispatchType* )atomic_load_explicit(&__musl_libc_globals.so_dispatch_table, memory_order_acquire);
573 atomic_store_explicit(&__musl_libc_globals.current_dispatch_table, (volatile long long)so_dispatch_value, memory_order_seq_cst);
574 }
575 }
576
__uninstal_malloc_hook()577 static void __uninstal_malloc_hook()
578 {
579 if (__get_memleak_hook_flag()) {
580 return;
581 }
582 if (!atomic_load_explicit(&__hook_enable_hook_flag, memory_order_acquire)) {
583 return;
584 }
585 bool expected = true;
586 if (atomic_compare_exchange_strong_explicit(&__hook_enable_hook_flag, &expected, false, memory_order_release, memory_order_relaxed)) {
587 bool flag = __set_hook_flag(false);
588 __set_default_malloc();
589 on_end_func_t end_func = (on_end_func_t)(function_of_shared_lib[ON_END_FUNCTION]);
590 if (end_func) {
591 end_func();
592 }
593 }
594 }
595
__install_memleak_tracker_hook(int32_t sigNum,siginfo_t * info,void * ptr)596 static void __install_memleak_tracker_hook(int32_t sigNum, siginfo_t *info, void *ptr)
597 {
598 if (__get_global_hook_flag()) {
599 return;
600 }
601 atomic_store_explicit(&__memleak_hook_flag, (volatile bool)true, memory_order_seq_cst);
602 volatile void* memleak_ever_handle = (volatile void* )atomic_load_explicit(&memleak_ever_shared_library_handle, memory_order_acquire);
603 if (memleak_ever_handle != NULL) {
604 atomic_store_explicit(&ohos_malloc_hook_shared_library, (volatile long long)memleak_ever_handle, memory_order_seq_cst);
605 } else {
606 atomic_store_explicit(&ohos_malloc_hook_shared_library, (volatile long long)0, memory_order_seq_cst);
607 }
608 volatile void* shared_library_handle = (volatile void* )atomic_load_explicit(&ohos_malloc_hook_shared_library, memory_order_acquire);
609 memLeakTypeContent = (unsigned int)(siginfo_t *)((info)->si_addr);
610 if (shared_library_handle == NULL) {
611 if (__hook_mode == STEP_HOOK_MODE) {
612 if (memLeakTypeContent & ADDR_NATIVE_ENABLE) {
613 atomic_store_explicit(&__musl_libc_globals.current_dispatch_table, (volatile const long long)&__ohos_malloc_hook_init_dispatch, memory_order_seq_cst);
614 atomic_store_explicit(&ohos_malloc_hook_shared_library, (volatile long long)-1, memory_order_seq_cst);
615 }
616 } else {
617 init_ohos_malloc_hook();
618 }
619 } else if (shared_library_handle != (void*)-1) {
620 if (checkLoadMallocMemTrack) {
621 __restore_hook_function_table();
622 on_start_func_t start_func = (on_start_func_t)(function_of_shared_lib[ON_START_FUNCTION]);
623 if (memLeakTypeContent & ADDR_NATIVE_ENABLE) {
624 volatile const struct MallocDispatchType* memleak_tracker_so_dispatch_value = (volatile const struct MallocDispatchType* )atomic_load_explicit(&__musl_libc_globals.memleak_tracker_so_dispatch_table, memory_order_acquire);
625 atomic_store_explicit(&__musl_libc_globals.current_dispatch_table, (volatile long long)memleak_tracker_so_dispatch_value, memory_order_seq_cst);
626 }
627 if (start_func && !start_func(memLeakTypeContent)) {
628 // __musl_log(__MUSL_LOG_ERROR, "%s: failed to enable malloc\n", getprogname());
629 clear_function_table();
630 }
631 if (memLeakTypeContent & ADDR_NATIVE_CLEAR) {
632 atomic_store_explicit(&__memleak_hook_flag, (volatile bool)false, memory_order_seq_cst);
633 bool flag = __set_hook_flag(false);
634 __set_default_malloc();
635 on_end_func_t end_func = (on_end_func_t)(function_of_shared_lib[ON_END_FUNCTION]);
636 if (end_func) {
637 end_func();
638 }
639 memLeakTypeContent = 0;
640 }
641 }
642 }
643 }
644
645
__install_malloc_hook_signal_handler()646 static void __install_malloc_hook_signal_handler()
647 {
648 struct sigaction actionInstallHook = {};
649 actionInstallHook.sa_handler = __install_malloc_hook;
650 sigemptyset(&actionInstallHook.sa_mask);
651 sigaddset(&actionInstallHook.sa_mask, MUSL_SIGNAL_UNHOOK);
652 sigaction(MUSL_SIGNAL_HOOK, &actionInstallHook, NULL);
653
654 struct sigaction actionDef = {};
655 actionDef.sa_handler = __uninstal_malloc_hook;
656 sigemptyset(&actionDef.sa_mask);
657 sigaddset(&actionDef.sa_mask, MUSL_SIGNAL_HOOK);
658 sigaction(MUSL_SIGNAL_UNHOOK, &actionDef, NULL);
659
660 struct sigaction actionInstallMemleakHook = {};
661 actionInstallMemleakHook.sa_handler = NULL;
662 actionInstallMemleakHook.sa_sigaction = __install_memleak_tracker_hook;
663 sigemptyset(&actionInstallMemleakHook.sa_mask);
664 sigaddset(&actionInstallMemleakHook.sa_mask, MUSL_SIGNAL_MEMCHECK);
665 actionInstallMemleakHook.sa_flags = SA_SIGINFO;
666 actionInstallMemleakHook.sa_restorer = NULL;
667 sigaction(MUSL_SIGNAL_MEMCHECK, &actionInstallMemleakHook, NULL);
668 }
669
__initialize_malloc()670 static void __initialize_malloc()
671 {
672 __install_malloc_hook_signal_handler();
673 #ifdef USE_JEMALLOC_RECYCLE_FUNC
674 init_jemalloc_recycle_handler();
675 #endif
676 }
677
__musl_initialize()678 __attribute__((constructor(1))) static void __musl_initialize()
679 {
680 atomic_store_explicit(&__hook_enable_hook_flag, (volatile bool)false, memory_order_seq_cst);
681 atomic_store_explicit(&__memleak_hook_flag, (volatile bool)false, memory_order_seq_cst);
682 __set_default_malloc();
683 char hook_process_path[MAX_PROC_NAME_SIZE + 1] = {0};
684 parse_hook_variable(&__hook_mode, hook_process_path, sizeof(hook_process_path) - 1);
685 MUSL_LOGI("HiProfiler, __musl_initialize %{public}d", __hook_mode);
686 if (__hook_mode == STARTUP_HOOK_MODE) {
687 char proc_name[MAX_PROC_NAME_SIZE + 1] = {0};
688 if (get_proc_name(getpid(), proc_name, sizeof(proc_name) - 1)) {
689 const char *pos = strrchr(proc_name, '/');
690 const char* file_name;
691 if (pos != NULL) {
692 file_name = pos + 1;
693 } else {
694 file_name = proc_name;
695 }
696 MUSL_LOGI("HiProfiler, current proc %{public}s, , target proc %{public}s", file_name, hook_process_path);
697 if (strncmp(file_name, hook_process_path, strlen(hook_process_path)) == 0) {
698 atomic_store_explicit(&__hook_enable_hook_flag, (volatile bool)true, memory_order_seq_cst);
699 init_ohos_malloc_hook();
700 } else {
701 __hook_mode = STEP_HOOK_MODE;
702 }
703 } else {
704 __hook_mode = STEP_HOOK_MODE;
705 }
706 }
707 __initialize_malloc();
708 errno = 0;
709 }
710 #endif