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