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