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