• 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);
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_param()108 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_cache()304 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_handler()311 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_table()359 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 		}
366 		function_of_ohos_malloc_shared_lib[i] = NULL;
367 	}
368 }
369 
init_malloc_hook_shared_library(void * shared_library_handle,const char * shared_lib,const char * prefix,struct MallocDispatchType * dispatch_table)370 bool init_malloc_hook_shared_library(void* shared_library_handle, const char* shared_lib, const char* prefix, struct MallocDispatchType* dispatch_table)
371 {
372 	static const char* names[] = {
373 		"initialize",
374 		"finalize",
375 		"get_hook_flag",
376 		"set_hook_flag",
377 		"on_start",
378 		"on_end",
379 		"send_hook_misc_data",
380 		"get_hook_config",
381 	};
382 
383 	for (int i = 0; i < LAST_FUNCTION; i++) {
384 		char symbol[MAX_SYM_NAME_SIZE];
385 		snprintf(symbol, sizeof(symbol), "%s_%s", prefix, names[i]);
386 		function_of_shared_lib[i] = dlsym(shared_library_handle, symbol);
387 		if (function_of_shared_lib[i] == NULL) {
388 			// __musl_log(__MUSL_LOG_ERROR, "%s: %s routine not found in %s\n", getprogname(), symbol, shared_lib);
389 			clear_function_table();
390 			return false;
391 		}
392 		if (__get_memleak_hook_flag()) {
393 			function_of_memleak_shared_lib[i] = function_of_shared_lib[i];
394 		}
395 		function_of_ohos_malloc_shared_lib[i] = function_of_shared_lib[i];
396 	}
397 
398 	if (!init_hook_functions(shared_library_handle, dispatch_table, prefix)) {
399 		clear_function_table();
400 		return false;
401 	}
402 
403 	return true;
404 }
405 
load_malloc_hook_shared_library(const char * shared_lib,const char * prefix,struct MallocDispatchType * dispatch_table)406 void* load_malloc_hook_shared_library(const char* shared_lib, const char* prefix, struct MallocDispatchType* dispatch_table)
407 {
408 	void* shared_library_handle = NULL;
409 
410 	shared_library_handle = dlopen(shared_lib, RTLD_NOW | RTLD_LOCAL);
411 
412 	if (shared_library_handle == NULL) {
413 		MUSL_LOGI("HiProfiler, Unable to open shared library %{public}s: %{public}s.", shared_lib, dlerror());
414 		return NULL;
415 	}
416 
417 	if (!init_malloc_hook_shared_library(shared_library_handle, shared_lib, prefix, dispatch_table)) {
418 		dlclose(shared_library_handle);
419 		shared_library_handle = NULL;
420 	}
421 	MUSL_LOGI("HiProfiler, load_malloc_hook_shared_library success.");
422 	return shared_library_handle;
423 }
424 
425 typedef void (*finalize_func_t)();
426 typedef bool (*init_func_t)(const struct MallocDispatchType*, bool*, const char*);
427 typedef bool (*on_start_func_t)();
428 typedef bool (*on_end_func_t)();
429 
malloc_finalize()430 static void malloc_finalize()
431 {
432 	__set_hook_flag(false);
433 	((finalize_func_t)function_of_shared_lib[FINALIZE_FUNCTION])();
434 
435 	fclose(stdin);
436 	fclose(stdout);
437 	fclose(stderr);
438 }
439 
finish_install_ohos_malloc_hooks(struct musl_libc_globals * globals,const char * options,const char * prefix,void * shared_library_handle)440 bool finish_install_ohos_malloc_hooks(struct musl_libc_globals* globals, const char* options, const char* prefix, void* shared_library_handle)
441 {
442 	init_func_t init_func = (init_func_t)(function_of_shared_lib[INITIALIZE_FUNCTION]);
443 	if (!init_func(&__libc_malloc_default_dispatch, NULL, options)) {
444 		// __musl_log(__MUSL_LOG_ERROR, "%s: failed to enable malloc %s\n", getprogname(), prefix);
445 		clear_function_table();
446 		return false;
447 	}
448 	on_start_func_t start_func = (on_start_func_t)(function_of_shared_lib[ON_START_FUNCTION]);
449 	if (!start_func(__uninstal_malloc_hook)) {
450 		// __musl_log(__MUSL_LOG_ERROR, "%s: failed to start %s\n", getprogname(), prefix);
451 		clear_function_table();
452 		return false;
453 	}
454 	atomic_store_explicit(&ohos_malloc_hook_shared_library, (volatile long long)shared_library_handle, memory_order_seq_cst);
455 	atomic_store_explicit(&__musl_libc_globals.so_dispatch_table, (volatile long long)&globals->malloc_dispatch_table, memory_order_seq_cst);
456 	atomic_store_explicit(&__musl_libc_globals.current_dispatch_table, (volatile long long)&globals->malloc_dispatch_table, memory_order_seq_cst);
457 	if (__get_memleak_hook_flag() && checkLoadMallocMemTrack) {
458 		if (!start_func(memLeakTypeContent)) {
459 			clear_function_table();
460 			return false;
461 		}
462 		atomic_store_explicit(&__musl_libc_globals.memleak_tracker_so_dispatch_table, (volatile long long)&globals->memleak_tracker_malloc_dispatch_table, memory_order_seq_cst);
463 		atomic_store_explicit(&__musl_libc_globals.current_dispatch_table, (volatile long long)&globals->memleak_tracker_malloc_dispatch_table, memory_order_seq_cst);
464 	}
465 	int ret_value = atexit(malloc_finalize);
466 	if (ret_value != 0) {
467 		// __musl_log(__MUSL_LOG_ERROR, "failed to set atexit cleanup function: %d\n", ret_value);
468 	}
469 	return true;
470 }
471 
is_empty_string(const char * str)472 static bool is_empty_string(const char* str)
473 {
474 	while (*str) {
475 		if (!isspace((unsigned char)(*str))) {
476 			return false;
477 		}
478 	}
479 	return true;
480 }
481 
install_ohos_malloc_hook(struct musl_libc_globals * globals,const char * shared_lib,const char * prefix)482 static void install_ohos_malloc_hook(struct musl_libc_globals* globals, const char* shared_lib, const char* prefix)
483 {
484 	volatile void* shared_library_handle = (volatile void *)atomic_load_explicit(&ohos_malloc_hook_shared_library, memory_order_acquire);
485 	assert(shared_library_handle == NULL || shared_library_handle == (volatile void*)-1);
486 	if (__get_memleak_hook_flag()) {
487 		shared_library_handle = (volatile void*)load_malloc_hook_shared_library(shared_lib, prefix, &globals->memleak_tracker_malloc_dispatch_table);
488 	}
489 	shared_library_handle = (volatile void*)load_malloc_hook_shared_library(shared_lib, prefix, &globals->malloc_dispatch_table);
490 	if (shared_library_handle == NULL) {
491 		// __musl_log(__MUSL_LOG_ERROR, "Can't load shared library '%s'\n", __malloc_hook_shared_lib);
492 		return;
493 	}
494 
495 	if (finish_install_ohos_malloc_hooks(globals, NULL, prefix, shared_library_handle)) {
496 		if (strncmp(__malloc_hook_function_prefix, prefix, strlen(prefix)) == 0) {
497 			atomic_store_explicit(&ohos_malloc_ever_shared_library_handle, (volatile long long)shared_library_handle, memory_order_seq_cst);
498 		} else {
499 			atomic_store_explicit(&memleak_ever_shared_library_handle, (volatile long long)shared_library_handle, memory_order_seq_cst);
500 		}
501 	} else {
502 		// __musl_log(__MUSL_LOG_ERROR, "finish_install_ohos_malloc_hooks failed\n");
503 		dlclose((void *)shared_library_handle);
504 		atomic_store_explicit(&ohos_malloc_hook_shared_library, (volatile long long)0, memory_order_seq_cst);
505 	}
506 }
507 
init_ohos_malloc_hook()508 static void* init_ohos_malloc_hook()
509 {
510 	if (__get_memleak_hook_flag()) {
511 		get_memleak_hook_param();
512 		if (checkLoadMallocMemTrack) {
513 			install_ohos_malloc_hook(&__musl_libc_globals, kMemTrackSharedLib, kMemTrackPrefix);
514 		}
515 	}
516 	if (__get_global_hook_flag()) {
517 		install_ohos_malloc_hook(&__musl_libc_globals, __malloc_hook_shared_lib, __malloc_hook_function_prefix);
518 	}
519 	return NULL;
520 }
521 
ohos_malloc_hook_init_function(size_t bytes)522 void* ohos_malloc_hook_init_function(size_t bytes)
523 {
524 	if (atomic_exchange(&__musl_libc_globals.current_dispatch_table, (volatile const long long)NULL)) {
525 		pthread_t thread_id;
526 		MUSL_LOGI("HiProfiler, ohos_malloc_hook_init_function, pthread_create.");
527 		if (pthread_create(&thread_id, NULL, init_ohos_malloc_hook, NULL) != 0) {
528 			// __musl_log(__MUSL_LOG_ERROR, "%s: ohos_malloc_hook: failed to pthread_create\n", getprogname());
529 		} else if (pthread_detach(thread_id) != 0) {
530 			// __musl_log(__MUSL_LOG_ERROR, "%s: ohos_malloc_hook: failed to pthread_detach\n", getprogname());
531 		}
532 	}
533 	void*ptr = MuslFunc(malloc)(bytes);
534 	return ptr;
535 
536 }
537 
__set_default_malloc()538 static void __set_default_malloc()
539 {
540 	atomic_store_explicit(&__musl_libc_globals.current_dispatch_table, (volatile const long long)NULL, memory_order_seq_cst);
541 }
542 
__restore_hook_function_table()543 static void __restore_hook_function_table()
544 {
545 	for (size_t i = 0; i < LAST_FUNCTION; i++) {
546 		if (__get_memleak_hook_flag()) {
547 			function_of_shared_lib[i] = function_of_memleak_shared_lib[i];
548 		}
549 		function_of_shared_lib[i] = function_of_ohos_malloc_shared_lib[i];
550 	}
551 }
552 
__install_malloc_hook()553 static void __install_malloc_hook()
554 {
555 	if (__get_memleak_hook_flag()) {
556 		return;
557 	}
558 	atomic_store_explicit(&__hook_enable_hook_flag, (volatile bool)true, memory_order_seq_cst);
559 	volatile void* ohos_malloc_ever_handle = (volatile void*)atomic_load_explicit(&ohos_malloc_ever_shared_library_handle, memory_order_acquire);
560 	if (ohos_malloc_ever_handle != NULL) {
561 		atomic_store_explicit(&ohos_malloc_hook_shared_library, (volatile long long)ohos_malloc_ever_handle, memory_order_seq_cst);
562 	} else {
563 		atomic_store_explicit(&ohos_malloc_hook_shared_library, (volatile long long)0, memory_order_seq_cst);
564 	}
565 	volatile void* shared_library_handle = (volatile void*)atomic_load_explicit(&ohos_malloc_hook_shared_library, memory_order_acquire);
566 	if (shared_library_handle == NULL) {
567 		MUSL_LOGI("HiProfiler, __install_malloc_hook __hook_mode %{public}d", __hook_mode);
568 		if (__hook_mode == STEP_HOOK_MODE) {
569 			atomic_store_explicit(&__musl_libc_globals.current_dispatch_table, (volatile const long long)&__ohos_malloc_hook_init_dispatch, memory_order_seq_cst);
570 			atomic_store_explicit(&ohos_malloc_hook_shared_library, (volatile long long)-1, memory_order_seq_cst);
571 		} else {
572 			init_ohos_malloc_hook();
573 		}
574 	} else if (shared_library_handle != (void*)-1) {
575 		__restore_hook_function_table();
576 		on_start_func_t start_func = (on_start_func_t)(function_of_shared_lib[ON_START_FUNCTION]);
577 		if (start_func && !start_func(__uninstal_malloc_hook)) {
578 			// __musl_log(__MUSL_LOG_ERROR, "%s: failed to enable malloc\n", getprogname());
579 		}
580 		volatile const struct MallocDispatchType* so_dispatch_value = (volatile const struct MallocDispatchType*)atomic_load_explicit(&__musl_libc_globals.so_dispatch_table, memory_order_acquire);
581 		atomic_store_explicit(&__musl_libc_globals.current_dispatch_table, (volatile long long)so_dispatch_value, memory_order_seq_cst);
582 	}
583 }
584 
__uninstal_malloc_hook()585 static void __uninstal_malloc_hook()
586 {
587 	if (__get_memleak_hook_flag()) {
588 		return;
589 	}
590 	if (!atomic_load_explicit(&__hook_enable_hook_flag, memory_order_acquire)) {
591 		return;
592 	}
593 	bool expected = true;
594 	if (atomic_compare_exchange_strong_explicit(&__hook_enable_hook_flag, &expected, false, memory_order_release, memory_order_relaxed)) {
595 		bool flag = __set_hook_flag(false);
596 		__set_default_malloc();
597 		on_end_func_t end_func = (on_end_func_t)(function_of_shared_lib[ON_END_FUNCTION]);
598 		if (end_func) {
599 			end_func();
600 		}
601 	}
602 }
603 
__install_memleak_tracker_hook(int32_t sigNum,siginfo_t * info,void * ptr)604 static void __install_memleak_tracker_hook(int32_t sigNum, siginfo_t *info, void *ptr)
605 {
606 	if (__get_global_hook_flag()) {
607 		return;
608 	}
609 	atomic_store_explicit(&__memleak_hook_flag, (volatile bool)true, memory_order_seq_cst);
610 	volatile void* memleak_ever_handle = (volatile void*)atomic_load_explicit(&memleak_ever_shared_library_handle, memory_order_acquire);
611 	if (memleak_ever_handle != NULL) {
612 		atomic_store_explicit(&ohos_malloc_hook_shared_library, (volatile long long)memleak_ever_handle, memory_order_seq_cst);
613 	} else {
614 		atomic_store_explicit(&ohos_malloc_hook_shared_library, (volatile long long)0, memory_order_seq_cst);
615 	}
616 	volatile void* shared_library_handle = (volatile void*)atomic_load_explicit(&ohos_malloc_hook_shared_library, memory_order_acquire);
617 	memLeakTypeContent = (unsigned int)(siginfo_t *)((info)->si_addr);
618 	if (shared_library_handle == NULL) {
619 		if (__hook_mode == STEP_HOOK_MODE) {
620 			if (memLeakTypeContent & ADDR_NATIVE_ENABLE) {
621 				atomic_store_explicit(&__musl_libc_globals.current_dispatch_table, (volatile const long long)&__ohos_malloc_hook_init_dispatch, memory_order_seq_cst);
622 				atomic_store_explicit(&ohos_malloc_hook_shared_library, (volatile long long)-1, memory_order_seq_cst);
623 			}
624 		} else {
625 			init_ohos_malloc_hook();
626 		}
627 	} else if (shared_library_handle != (void*)-1) {
628 		if (checkLoadMallocMemTrack) {
629 			__restore_hook_function_table();
630 			on_start_func_t start_func = (on_start_func_t)(function_of_shared_lib[ON_START_FUNCTION]);
631 			if (memLeakTypeContent & ADDR_NATIVE_ENABLE) {
632 				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);
633 				atomic_store_explicit(&__musl_libc_globals.current_dispatch_table, (volatile long long)memleak_tracker_so_dispatch_value, memory_order_seq_cst);
634 			}
635 			if (start_func && !start_func(memLeakTypeContent)) {
636 				// __musl_log(__MUSL_LOG_ERROR, "%s: failed to enable malloc\n", getprogname());
637 				clear_function_table();
638 			}
639 			if (memLeakTypeContent & ADDR_NATIVE_CLEAR) {
640 				atomic_store_explicit(&__memleak_hook_flag, (volatile bool)false, memory_order_seq_cst);
641 				bool flag = __set_hook_flag(false);
642 				__set_default_malloc();
643 				on_end_func_t end_func = (on_end_func_t)(function_of_shared_lib[ON_END_FUNCTION]);
644 				if (end_func) {
645 					end_func();
646 				}
647 				memLeakTypeContent = 0;
648 			}
649 		}
650 	}
651 }
652 
653 
__install_malloc_hook_signal_handler()654 static void __install_malloc_hook_signal_handler()
655 {
656 	struct sigaction actionInstallHook = {};
657 	actionInstallHook.sa_handler = __install_malloc_hook;
658 	sigemptyset(&actionInstallHook.sa_mask);
659 	sigaddset(&actionInstallHook.sa_mask, MUSL_SIGNAL_UNHOOK);
660 	sigaction(MUSL_SIGNAL_HOOK, &actionInstallHook, NULL);
661 
662 	struct sigaction actionDef = {};
663 	actionDef.sa_handler = __uninstal_malloc_hook;
664 	sigemptyset(&actionDef.sa_mask);
665 	sigaddset(&actionDef.sa_mask, MUSL_SIGNAL_HOOK);
666 	sigaction(MUSL_SIGNAL_UNHOOK, &actionDef, NULL);
667 
668 	struct sigaction actionInstallMemleakHook = {};
669 	actionInstallMemleakHook.sa_handler = NULL;
670 	actionInstallMemleakHook.sa_sigaction = __install_memleak_tracker_hook;
671 	sigemptyset(&actionInstallMemleakHook.sa_mask);
672 	sigaddset(&actionInstallMemleakHook.sa_mask, MUSL_SIGNAL_MEMCHECK);
673 	actionInstallMemleakHook.sa_flags = SA_SIGINFO;
674 	actionInstallMemleakHook.sa_restorer = NULL;
675 	sigaction(MUSL_SIGNAL_MEMCHECK, &actionInstallMemleakHook, NULL);
676 }
677 
__initialize_malloc()678 static void __initialize_malloc()
679 {
680 	__install_malloc_hook_signal_handler();
681 #ifdef USE_JEMALLOC_RECYCLE_FUNC
682 	init_jemalloc_recycle_handler();
683 #endif
684 }
685 
__musl_initialize()686 __attribute__((constructor(1))) static void __musl_initialize()
687 {
688 	atomic_store_explicit(&__hook_enable_hook_flag, (volatile bool)false, memory_order_seq_cst);
689 	atomic_store_explicit(&__memleak_hook_flag, (volatile bool)false, memory_order_seq_cst);
690 	__set_default_malloc();
691 	char hook_process_path[MAX_PROC_NAME_SIZE + 1] = {0};
692 	parse_hook_variable(&__hook_mode, hook_process_path, sizeof(hook_process_path) - 1);
693 	MUSL_LOGI("HiProfiler, __musl_initialize %{public}d", __hook_mode);
694 	if (__hook_mode == STARTUP_HOOK_MODE) {
695 		char proc_name[MAX_PROC_NAME_SIZE + 1] = {0};
696 		if (get_proc_name(getpid(), proc_name, sizeof(proc_name) - 1)) {
697 			const char *pos = strrchr(proc_name, '/');
698 			const char* file_name;
699 			if (pos != NULL) {
700 				file_name = pos + 1;
701 			} else {
702 				file_name = proc_name;
703 			}
704 			MUSL_LOGI("HiProfiler, current proc %{public}s, , target proc %{public}s", file_name, hook_process_path);
705 			if (strncmp(file_name, hook_process_path, strlen(hook_process_path)) == 0) {
706 				atomic_store_explicit(&__hook_enable_hook_flag, (volatile bool)true, memory_order_seq_cst);
707 				init_ohos_malloc_hook();
708 			} else {
709 				__hook_mode = STEP_HOOK_MODE;
710 			}
711 		} else {
712 			__hook_mode = STEP_HOOK_MODE;
713 		}
714 	}
715 	__initialize_malloc();
716 	errno = 0;
717 }
718 #endif
719