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