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