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