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 const char ARK_LIB_NAME[] = "libark_jsruntime.so";
37
38 void* g_handle = nullptr;
39 pthread_mutex_t g_mutex;
40 int (*g_getArkNativeFrameInfoFn)(int, uintptr_t*, uintptr_t*, uintptr_t*, JsFrame*, size_t&);
41 int (*g_stepArkFn)(void*, OHOS::HiviewDFX::ReadMemFunc, uintptr_t*, uintptr_t*, uintptr_t*, uintptr_t*, bool*);
42 int (*g_stepArkWithJitFn)(OHOS::HiviewDFX::ArkUnwindParam*);
43 int (*g_jitCodeWriteFileFn)(void*, OHOS::HiviewDFX::ReadMemFunc, int, const uintptr_t* const, const size_t);
44 int (*g_parseArkFileInfoFn)(uintptr_t, uintptr_t, uintptr_t, const char*, uintptr_t, JsFunction*);
45 int (*g_parseArkFrameInfoLocalFn)(uintptr_t, uintptr_t, uintptr_t, uintptr_t, JsFunction*);
46 int (*g_parseArkFrameInfoFn)(uintptr_t, uintptr_t, uintptr_t, uintptr_t, uint8_t*, uint64_t, uintptr_t, JsFunction*);
47 int (*g_translateArkFrameInfoFn)(uint8_t*, uint64_t, JsFunction*);
48 int (*g_arkCreateJsSymbolExtractorFn)(uintptr_t*);
49 int (*g_arkDestoryJsSymbolExtractorFn)(uintptr_t);
50 int (*g_arkCreateLocalFn)();
51 int (*g_arkDestroyLocalFn)();
52
GetLibArkHandle()53 bool GetLibArkHandle()
54 {
55 if (g_handle != nullptr) {
56 return true;
57 }
58 g_handle = dlopen(ARK_LIB_NAME, RTLD_LAZY);
59 if (g_handle == nullptr) {
60 LOGU("Failed to load library(%s).", dlerror());
61 return false;
62 }
63 return true;
64 }
65 }
66
67 #define DLSYM_ARK_FUNC(FuncName, DlsymFuncName) { \
68 pthread_mutex_lock(&g_mutex); \
69 do { \
70 if ((DlsymFuncName) != nullptr) { \
71 break; \
72 } \
73 if (!GetLibArkHandle()) { \
74 break; \
75 } \
76 *(void**)(&(DlsymFuncName)) = dlsym(g_handle, (FuncName)); \
77 if ((DlsymFuncName) == NULL) { \
78 LOGE("Failed to dlsym(%s), error: %s", (FuncName), dlerror()); \
79 break; \
80 } \
81 } while (false); \
82 pthread_mutex_unlock(&g_mutex); \
83 }
84
ArkCreateJsSymbolExtractor(uintptr_t * extractorPtr)85 int DfxArk::ArkCreateJsSymbolExtractor(uintptr_t* extractorPtr)
86 {
87 if (g_arkCreateJsSymbolExtractorFn != nullptr) {
88 return g_arkCreateJsSymbolExtractorFn(extractorPtr);
89 }
90
91 const char* arkFuncName = "ark_create_js_symbol_extractor";
92 DLSYM_ARK_FUNC(arkFuncName, g_arkCreateJsSymbolExtractorFn)
93
94 if (g_arkCreateJsSymbolExtractorFn != nullptr) {
95 return g_arkCreateJsSymbolExtractorFn(extractorPtr);
96 }
97 return -1;
98 }
99
ArkDestoryJsSymbolExtractor(uintptr_t extractorPtr)100 int DfxArk::ArkDestoryJsSymbolExtractor(uintptr_t extractorPtr)
101 {
102 if (g_arkDestoryJsSymbolExtractorFn != nullptr) {
103 return g_arkDestoryJsSymbolExtractorFn(extractorPtr);
104 }
105
106 const char* arkFuncName = "ark_destory_js_symbol_extractor";
107 DLSYM_ARK_FUNC(arkFuncName, g_arkDestoryJsSymbolExtractorFn)
108
109 if (g_arkDestoryJsSymbolExtractorFn != nullptr) {
110 return g_arkDestoryJsSymbolExtractorFn(extractorPtr);
111 }
112 return -1;
113 }
114
ArkCreateLocal()115 int DfxArk::ArkCreateLocal()
116 {
117 if (g_arkCreateLocalFn != nullptr) {
118 return g_arkCreateLocalFn();
119 }
120
121 const char* arkFuncName = "ark_create_local";
122 DLSYM_ARK_FUNC(arkFuncName, g_arkCreateLocalFn)
123
124 if (g_arkCreateLocalFn != nullptr) {
125 return g_arkCreateLocalFn();
126 }
127 return -1;
128 }
129
ArkDestroyLocal()130 int DfxArk::ArkDestroyLocal()
131 {
132 if (g_arkDestroyLocalFn != nullptr) {
133 return g_arkDestroyLocalFn();
134 }
135
136 const char* arkFuncName = "ark_destroy_local";
137 DLSYM_ARK_FUNC(arkFuncName, g_arkDestroyLocalFn)
138
139 if (g_arkDestroyLocalFn != nullptr) {
140 return g_arkDestroyLocalFn();
141 }
142 return -1;
143 }
144
ParseArkFileInfo(uintptr_t byteCodePc,uintptr_t methodid,uintptr_t mapBase,const char * name,uintptr_t extractorPtr,JsFunction * jsFunction)145 int DfxArk::ParseArkFileInfo(uintptr_t byteCodePc, uintptr_t methodid, uintptr_t mapBase, const char* name,
146 uintptr_t extractorPtr, JsFunction *jsFunction)
147 {
148 if (g_parseArkFileInfoFn != nullptr) {
149 return g_parseArkFileInfoFn(byteCodePc, methodid, mapBase, name, extractorPtr, jsFunction);
150 }
151
152 const char* arkFuncName = "ark_parse_js_file_info";
153 DLSYM_ARK_FUNC(arkFuncName, g_parseArkFileInfoFn)
154
155 if (g_parseArkFileInfoFn != nullptr) {
156 return g_parseArkFileInfoFn(byteCodePc, methodid, mapBase, name, extractorPtr, jsFunction);
157 }
158 return -1;
159 }
160
ParseArkFrameInfoLocal(uintptr_t byteCodePc,uintptr_t methodid,uintptr_t mapBase,uintptr_t offset,JsFunction * jsFunction)161 int DfxArk::ParseArkFrameInfoLocal(uintptr_t byteCodePc, uintptr_t methodid, uintptr_t mapBase,
162 uintptr_t offset, JsFunction *jsFunction)
163 {
164 if (g_parseArkFrameInfoLocalFn != nullptr) {
165 return g_parseArkFrameInfoLocalFn(byteCodePc, methodid, mapBase, offset, jsFunction);
166 }
167
168 const char* arkFuncName = "ark_parse_js_frame_info_local";
169 DLSYM_ARK_FUNC(arkFuncName, g_parseArkFrameInfoLocalFn)
170
171 if (g_parseArkFrameInfoLocalFn != nullptr) {
172 return g_parseArkFrameInfoLocalFn(byteCodePc, methodid, mapBase, offset, jsFunction);
173 }
174 return -1;
175 }
176
ParseArkFrameInfo(uintptr_t byteCodePc,uintptr_t mapBase,uintptr_t loadOffset,uint8_t * data,uint64_t dataSize,uintptr_t extractorPtr,JsFunction * jsFunction)177 int DfxArk::ParseArkFrameInfo(uintptr_t byteCodePc, uintptr_t mapBase, uintptr_t loadOffset,
178 uint8_t *data, uint64_t dataSize, uintptr_t extractorPtr, JsFunction *jsFunction)
179 {
180 return ParseArkFrameInfo(byteCodePc, 0, mapBase, loadOffset, data, dataSize, extractorPtr, jsFunction);
181 }
182
ParseArkFrameInfo(uintptr_t byteCodePc,uintptr_t methodid,uintptr_t mapBase,uintptr_t loadOffset,uint8_t * data,uint64_t dataSize,uintptr_t extractorPtr,JsFunction * jsFunction)183 int DfxArk::ParseArkFrameInfo(uintptr_t byteCodePc, uintptr_t methodid, uintptr_t mapBase, uintptr_t loadOffset,
184 uint8_t *data, uint64_t dataSize, uintptr_t extractorPtr, JsFunction *jsFunction)
185 {
186 if (g_parseArkFrameInfoFn != nullptr) {
187 return g_parseArkFrameInfoFn(byteCodePc, methodid, mapBase, loadOffset, data, dataSize,
188 extractorPtr, jsFunction);
189 }
190
191 const char* arkFuncName = "ark_parse_js_frame_info";
192 DLSYM_ARK_FUNC(arkFuncName, g_parseArkFrameInfoFn)
193
194 if (g_parseArkFrameInfoFn != nullptr) {
195 return g_parseArkFrameInfoFn(byteCodePc, methodid, mapBase, loadOffset, data, dataSize,
196 extractorPtr, jsFunction);
197 }
198 return -1;
199 }
200
TranslateArkFrameInfo(uint8_t * data,uint64_t dataSize,JsFunction * jsFunction)201 int DfxArk::TranslateArkFrameInfo(uint8_t *data, uint64_t dataSize, JsFunction *jsFunction)
202 {
203 if (g_translateArkFrameInfoFn != nullptr) {
204 return g_translateArkFrameInfoFn(data, dataSize, jsFunction);
205 }
206
207 const char* arkFuncName = "ark_translate_js_frame_info";
208 DLSYM_ARK_FUNC(arkFuncName, g_translateArkFrameInfoFn)
209
210 if (g_translateArkFrameInfoFn != nullptr) {
211 return g_translateArkFrameInfoFn(data, dataSize, jsFunction);
212 }
213 return -1;
214 }
215
StepArkFrame(void * obj,OHOS::HiviewDFX::ReadMemFunc readMemFn,uintptr_t * fp,uintptr_t * sp,uintptr_t * pc,uintptr_t * methodid,bool * isJsFrame)216 int DfxArk::StepArkFrame(void *obj, OHOS::HiviewDFX::ReadMemFunc readMemFn,
217 uintptr_t *fp, uintptr_t *sp, uintptr_t *pc, uintptr_t* methodid, bool *isJsFrame)
218 {
219 if (g_stepArkFn != nullptr) {
220 return g_stepArkFn(obj, readMemFn, fp, sp, pc, methodid, isJsFrame);
221 }
222
223 const char* arkFuncName = "step_ark";
224 DLSYM_ARK_FUNC(arkFuncName, g_stepArkFn)
225
226 if (g_stepArkFn != nullptr) {
227 return g_stepArkFn(obj, readMemFn, fp, sp, pc, methodid, isJsFrame);
228 }
229 return -1;
230 }
231
StepArkFrameWithJit(OHOS::HiviewDFX::ArkUnwindParam * arkPrama)232 int DfxArk::StepArkFrameWithJit(OHOS::HiviewDFX::ArkUnwindParam* arkPrama)
233 {
234 if (g_stepArkWithJitFn != nullptr) {
235 return g_stepArkWithJitFn(arkPrama);
236 }
237
238 const char* const arkFuncName = "step_ark_with_record_jit";
239 DLSYM_ARK_FUNC(arkFuncName, g_stepArkWithJitFn)
240
241 if (g_stepArkWithJitFn != nullptr) {
242 return g_stepArkWithJitFn(arkPrama);
243 }
244 return -1;
245 }
246
JitCodeWriteFile(void * ctx,OHOS::HiviewDFX::ReadMemFunc readMemFn,int fd,const uintptr_t * const jitCodeArray,const size_t jitSize)247 int DfxArk::JitCodeWriteFile(void* ctx, OHOS::HiviewDFX::ReadMemFunc readMemFn, int fd,
248 const uintptr_t* const jitCodeArray, const size_t jitSize)
249 {
250 if (g_jitCodeWriteFileFn != nullptr) {
251 return g_jitCodeWriteFileFn(ctx, readMemFn, fd, jitCodeArray, jitSize);
252 }
253
254 const char* const arkFuncName = "ark_write_jit_code";
255 DLSYM_ARK_FUNC(arkFuncName, g_jitCodeWriteFileFn)
256
257 if (g_jitCodeWriteFileFn != nullptr) {
258 return g_jitCodeWriteFileFn(ctx, readMemFn, fd, jitCodeArray, jitSize);
259 }
260 return -1;
261 }
262
GetArkNativeFrameInfo(int pid,uintptr_t & pc,uintptr_t & fp,uintptr_t & sp,JsFrame * frames,size_t & size)263 int DfxArk::GetArkNativeFrameInfo(int pid, uintptr_t& pc, uintptr_t& fp, uintptr_t& sp, JsFrame* frames, size_t& size)
264 {
265 if (g_getArkNativeFrameInfoFn != nullptr) {
266 return g_getArkNativeFrameInfoFn(pid, &pc, &fp, &sp, frames, size);
267 }
268
269 const char* arkFuncName = "get_ark_native_frame_info";
270 DLSYM_ARK_FUNC(arkFuncName, g_getArkNativeFrameInfoFn)
271
272 if (g_getArkNativeFrameInfoFn != nullptr) {
273 return g_getArkNativeFrameInfoFn(pid, &pc, &fp, &sp, frames, size);
274 }
275 return -1;
276 }
277 } // namespace HiviewDFX
278 } // namespace OHOS
279