1 /*
2 * Copyright (c) 2023 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 #include "dfx_ark.h"
17
18 #include <algorithm>
19 #include <cstdio>
20 #include <cstdlib>
21 #include <dlfcn.h>
22 #include <pthread.h>
23
24 #include "dfx_define.h"
25 #include "dfx_log.h"
26 #include "string_util.h"
27
28 namespace OHOS {
29 namespace HiviewDFX {
30 namespace {
31 #undef LOG_DOMAIN
32 #undef LOG_TAG
33 #define LOG_DOMAIN 0xD002D11
34 #define LOG_TAG "DfxArk"
35
36 static const char ARK_LIB_NAME[] = "libark_jsruntime.so";
37
38 static void* g_handle = nullptr;
39 static pthread_mutex_t g_mutex;
40 static int (*g_getArkNativeFrameInfoFn)(int, uintptr_t*, uintptr_t*, uintptr_t*, JsFrame*, size_t&);
41 static int (*g_stepArkManagedNativeFrameFn)(int, uintptr_t*, uintptr_t*, uintptr_t*, char*, size_t);
42 static int (*g_getArkJsHeapCrashInfoFn)(int, uintptr_t *, uintptr_t *, int, char *, size_t);
43 }
44
GetArkNativeFrameInfo(int pid,uintptr_t & pc,uintptr_t & fp,uintptr_t & sp,JsFrame * frames,size_t & size)45 int DfxArk::GetArkNativeFrameInfo(int pid, uintptr_t& pc, uintptr_t& fp, uintptr_t& sp, JsFrame* frames, size_t& size)
46 {
47 if (g_getArkNativeFrameInfoFn != nullptr) {
48 return g_getArkNativeFrameInfoFn(pid, &pc, &fp, &sp, frames, size);
49 }
50
51 pthread_mutex_lock(&g_mutex);
52 if (g_getArkNativeFrameInfoFn != nullptr) {
53 pthread_mutex_unlock(&g_mutex);
54 return g_getArkNativeFrameInfoFn(pid, &pc, &fp, &sp, frames, size);
55 }
56
57 if (g_handle == nullptr) {
58 g_handle = dlopen(ARK_LIB_NAME, RTLD_LAZY);
59 if (g_handle == nullptr) {
60 LOGU("Failed to load library(%s).", dlerror());
61 pthread_mutex_unlock(&g_mutex);
62 return -1;
63 }
64 }
65
66 *(void**)(&g_getArkNativeFrameInfoFn) = dlsym(g_handle, "get_ark_native_frame_info");
67 if (!g_getArkNativeFrameInfoFn) {
68 LOGU("Failed to find symbol(%s).", dlerror());
69 g_handle = nullptr;
70 pthread_mutex_unlock(&g_mutex);
71 return -1;
72 }
73
74 pthread_mutex_unlock(&g_mutex);
75 return g_getArkNativeFrameInfoFn(pid, &pc, &fp, &sp, frames, size);
76 }
77
StepArkManagedNativeFrame(int pid,uintptr_t & pc,uintptr_t & fp,uintptr_t & sp,char * buf,size_t bufSize)78 int DfxArk::StepArkManagedNativeFrame(int pid, uintptr_t& pc, uintptr_t& fp, uintptr_t& sp, char* buf, size_t bufSize)
79 {
80 if (g_stepArkManagedNativeFrameFn != nullptr) {
81 return g_stepArkManagedNativeFrameFn(pid, &pc, &fp, &sp, buf, bufSize);
82 }
83
84 pthread_mutex_lock(&g_mutex);
85 if (g_stepArkManagedNativeFrameFn != nullptr) {
86 pthread_mutex_unlock(&g_mutex);
87 return g_stepArkManagedNativeFrameFn(pid, &pc, &fp, &sp, buf, bufSize);
88 }
89
90 if (g_handle == nullptr) {
91 g_handle = dlopen(ARK_LIB_NAME, RTLD_LAZY);
92 if (g_handle == nullptr) {
93 LOGU("Failed to load library(%s).", dlerror());
94 pthread_mutex_unlock(&g_mutex);
95 return -1;
96 }
97 }
98
99 *(void**)(&g_stepArkManagedNativeFrameFn) = dlsym(g_handle, "step_ark_managed_native_frame");
100 if (!g_stepArkManagedNativeFrameFn) {
101 LOGU("Failed to find symbol(%s).", dlerror());
102 g_handle = nullptr;
103 pthread_mutex_unlock(&g_mutex);
104 return -1;
105 }
106
107 pthread_mutex_unlock(&g_mutex);
108 return g_stepArkManagedNativeFrameFn(pid, &pc, &fp, &sp, buf, bufSize);
109 }
110
GetArkJsHeapCrashInfo(int pid,uintptr_t & x20,uintptr_t & fp,int outJsInfo,char * buf,size_t bufSize)111 int DfxArk::GetArkJsHeapCrashInfo(int pid, uintptr_t& x20, uintptr_t& fp, int outJsInfo, char* buf, size_t bufSize)
112 {
113 if (g_getArkJsHeapCrashInfoFn != nullptr) {
114 return g_getArkJsHeapCrashInfoFn(pid, &x20, &fp, outJsInfo, buf, bufSize);
115 }
116
117 pthread_mutex_lock(&g_mutex);
118 if (g_getArkJsHeapCrashInfoFn != nullptr) {
119 pthread_mutex_unlock(&g_mutex);
120 return g_getArkJsHeapCrashInfoFn(pid, &x20, &fp, outJsInfo, buf, bufSize);
121 }
122
123 if (g_handle == nullptr) {
124 g_handle = dlopen(ARK_LIB_NAME, RTLD_LAZY);
125 if (g_handle == nullptr) {
126 LOGU("Failed to load library(%s).", dlerror());
127 pthread_mutex_unlock(&g_mutex);
128 return -1;
129 }
130 }
131
132 *(void**)(&g_getArkJsHeapCrashInfoFn) = dlsym(g_handle, "get_ark_js_heap_crash_info");
133 if (!g_getArkJsHeapCrashInfoFn) {
134 LOGU("Failed to find symbol(%s).", dlerror());
135 g_handle = nullptr;
136 pthread_mutex_unlock(&g_mutex);
137 return -1;
138 }
139
140 pthread_mutex_unlock(&g_mutex);
141 return g_getArkJsHeapCrashInfoFn(pid, &x20, &fp, outJsInfo, buf, bufSize);
142 }
143 } // namespace HiviewDFX
144 } // namespace OHOS
145