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