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/* 17The 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 23Case 1 represents "startup" mode, and the hooked process is "prog1 ", 24which loads hooking shared library when the program starts up. 25The path is added with two quotation marks because a quotation mark is a special charcter, 26which 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 53void* ohos_malloc_hook_init_function(size_t bytes); 54void default_memtrace(void* addr, size_t size, const char* tag, bool is_using) {} 55 56static 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) 74static char *__malloc_hook_shared_lib = "libnative_hook.z.so"; 75static char *__malloc_hook_function_prefix = "ohos_malloc_hook"; 76volatile atomic_llong ohos_malloc_hook_shared_library; 77static char *kMemTrackSharedLib = "libmemleak_tracker.so"; 78static char *kMemTrackPrefix = "track"; 79static char *kMemTrackPropertyEnable = "const.hiview.memleak_tracker.enable"; 80static char *kMemTrackSign = "true"; 81bool checkLoadMallocMemTrack = false; 82unsigned int memLeakTypeContent = 0; 83volatile atomic_llong memleak_ever_shared_library_handle; 84volatile atomic_llong ohos_malloc_ever_shared_library_handle; 85void* function_of_shared_lib[LAST_FUNCTION]; 86void* function_of_ohos_malloc_shared_lib[LAST_FUNCTION]; 87void* function_of_memleak_shared_lib[LAST_FUNCTION]; 88static enum EnumHookMode __hook_mode = STEP_HOOK_MODE; 89static void __uninstal_malloc_hook(); 90 91static 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 108static 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 122static 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 173static 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 192static 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 203static 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 214static 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 225static 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 236static 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 247static 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 258static 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 269static 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 280static 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 291static 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 303extern int je_reclaim_cache(); 304static 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 311static 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 324static 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 359static 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 371bool 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 408void* 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 427typedef void (*finalize_func_t)(); 428typedef bool (*init_func_t)(const struct MallocDispatchType*, bool*, const char*); 429typedef bool (*on_start_func_t)(); 430typedef bool (*on_end_func_t)(); 431 432static 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 442bool 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 476static 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 486static 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 513static 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 527void* 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 543static 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 548static 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 559static 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 591static 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 610static 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 660static 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 684static 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 692__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