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