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