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