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 /*
17 The 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 
23 Case 1 represents "startup" mode, and the hooked process is "prog1 ",
24 which loads hooking shared library when the program starts up.
25 The path is added with two quotation marks because a quotation mark is a special charcter,
26 which 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 
53 void* ohos_malloc_hook_init_function(size_t bytes);
default_memtrace(void* addr, size_t size, const char* tag, bool is_using)54 void default_memtrace(void* addr, size_t size, const char* tag, bool is_using) {}
55 
56 static 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)
74 static char *__malloc_hook_shared_lib = "libnative_hook.z.so";
75 static char *__malloc_hook_function_prefix = "ohos_malloc_hook";
76 volatile atomic_llong ohos_malloc_hook_shared_library;
77 static char *kMemTrackSharedLib = "libmemleak_tracker.so";
78 static char *kMemTrackPrefix = "track";
79 static char *kMemTrackPropertyEnable = "const.hiview.memleak_tracker.enable";
80 static char *kMemTrackSign = "true";
81 bool checkLoadMallocMemTrack = false;
82 unsigned int memLeakTypeContent = 0;
83 volatile atomic_llong memleak_ever_shared_library_handle;
84 volatile atomic_llong ohos_malloc_ever_shared_library_handle;
85 void* function_of_shared_lib[LAST_FUNCTION];
86 void* function_of_ohos_malloc_shared_lib[LAST_FUNCTION];
87 void* function_of_memleak_shared_lib[LAST_FUNCTION];
88 static enum EnumHookMode __hook_mode = STEP_HOOK_MODE;
89 static void __uninstal_malloc_hook();
90 
get_native_hook_param(char *buf, unsigned int buf_len)91 static 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 
get_memleak_hook_paramnull108 static 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 
parse_hook_variable(enum EnumHookMode* mode, char* path, int size)122 static 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 
get_proc_name(pid_t pid, char *buf, unsigned int buf_len)173 static 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 
init_malloc_function(void* malloc_shared_library_handler, MallocMallocType* func, const char* prefix)192 static 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 
init_free_function(void* malloc_shared_library_handler, MallocFreeType* func, const char* prefix)203 static 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 
init_mmap_function(void* malloc_shared_library_handler, MallocMmapType* func, const char* prefix)214 static 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 
init_munmap_function(void* malloc_shared_library_handler, MallocMunmapType* func, const char* prefix)225 static 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 
init_memtrace_function(void* malloc_shared_library_handler, MemTrace* func, const char* prefix)236 static 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 
init_calloc_function(void* malloc_shared_library_handler, MallocCallocType* func, const char* prefix)247 static 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 
init_realloc_function(void* malloc_shared_library_handler, MallocReallocType* func, const char* prefix)258 static 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 
init_malloc_usable_size_function(void* malloc_shared_library_handler, MallocMallocUsableSizeType* func, const char* prefix)269 static 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 
init_prctl_function(void* malloc_shared_library_handler, MallocPrctlType* func, const char* prefix)280 static 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 
init_aligned_alloc_function(void* malloc_shared_library_handler, MallocAlignedAllocType* func, const char* prefix)291 static 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
303 extern int je_reclaim_cache();
handle_recycle_cachenull304 static 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 
init_jemalloc_recycle_handlernull311 static 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 
init_hook_functions(void* shared_library_handler, struct MallocDispatchType* table, const char* prefix)324 static 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 
clear_function_tablenull359 static 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 
init_malloc_hook_shared_library(void* shared_library_handle, const char* shared_lib, const char* prefix, struct MallocDispatchType* dispatch_table)371 bool 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 
load_malloc_hook_shared_library(const char* shared_lib, const char* prefix, struct MallocDispatchType* dispatch_table)408 void* 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 
427 typedef void (*finalize_func_t)();
428 typedef bool (*init_func_t)(const struct MallocDispatchType*, bool*, const char*);
429 typedef bool (*on_start_func_t)();
430 typedef bool (*on_end_func_t)();
431 
malloc_finalizenull432 static 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 
finish_install_ohos_malloc_hooks(struct musl_libc_globals* globals, const char* options, const char* prefix, void* shared_library_handle)442 bool 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 
is_empty_string(const char* str)476 static 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 
install_ohos_malloc_hook(struct musl_libc_globals* globals, const char* shared_lib, const char* prefix)486 static 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 
init_ohos_malloc_hooknull513 static 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 
ohos_malloc_hook_init_function(size_t bytes)527 void* 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 
__set_default_mallocnull543 static 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 
__restore_hook_function_tablenull548 static 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 
__install_malloc_hooknull559 static 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 
__uninstal_malloc_hooknull591 static 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 
__install_memleak_tracker_hook(int32_t sigNum, siginfo_t *info, void *ptr)610 static 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 
__install_malloc_hook_signal_handlernull660 static 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 
__initialize_mallocnull684 static 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 
__musl_initializenull692 __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