• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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