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