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