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