1800b99b8Sopenharmony_ci/* 2800b99b8Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd. 3800b99b8Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4800b99b8Sopenharmony_ci * you may not use this file except in compliance with the License. 5800b99b8Sopenharmony_ci * You may obtain a copy of the License at 6800b99b8Sopenharmony_ci * 7800b99b8Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8800b99b8Sopenharmony_ci * 9800b99b8Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10800b99b8Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11800b99b8Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12800b99b8Sopenharmony_ci * See the License for the specific language governing permissions and 13800b99b8Sopenharmony_ci * limitations under the License. 14800b99b8Sopenharmony_ci */ 15800b99b8Sopenharmony_ci 16800b99b8Sopenharmony_ci#include "dfx_ark.h" 17800b99b8Sopenharmony_ci 18800b99b8Sopenharmony_ci#include <algorithm> 19800b99b8Sopenharmony_ci#include <cstdio> 20800b99b8Sopenharmony_ci#include <cstdlib> 21800b99b8Sopenharmony_ci#include <dlfcn.h> 22800b99b8Sopenharmony_ci#include <pthread.h> 23800b99b8Sopenharmony_ci 24800b99b8Sopenharmony_ci#include "dfx_define.h" 25800b99b8Sopenharmony_ci#include "dfx_log.h" 26800b99b8Sopenharmony_ci#include "string_util.h" 27800b99b8Sopenharmony_ci 28800b99b8Sopenharmony_cinamespace OHOS { 29800b99b8Sopenharmony_cinamespace HiviewDFX { 30800b99b8Sopenharmony_cinamespace { 31800b99b8Sopenharmony_ci#undef LOG_DOMAIN 32800b99b8Sopenharmony_ci#undef LOG_TAG 33800b99b8Sopenharmony_ci#define LOG_DOMAIN 0xD002D11 34800b99b8Sopenharmony_ci#define LOG_TAG "DfxArk" 35800b99b8Sopenharmony_ci 36800b99b8Sopenharmony_ciconst char ARK_LIB_NAME[] = "libark_jsruntime.so"; 37800b99b8Sopenharmony_ci 38800b99b8Sopenharmony_civoid* g_handle = nullptr; 39800b99b8Sopenharmony_cipthread_mutex_t g_mutex; 40800b99b8Sopenharmony_ciint (*g_getArkNativeFrameInfoFn)(int, uintptr_t*, uintptr_t*, uintptr_t*, JsFrame*, size_t&); 41800b99b8Sopenharmony_ciint (*g_stepArkFn)(void*, OHOS::HiviewDFX::ReadMemFunc, uintptr_t*, uintptr_t*, uintptr_t*, uintptr_t*, bool*); 42800b99b8Sopenharmony_ciint (*g_stepArkWithJitFn)(OHOS::HiviewDFX::ArkUnwindParam*); 43800b99b8Sopenharmony_ciint (*g_jitCodeWriteFileFn)(void*, OHOS::HiviewDFX::ReadMemFunc, int, const uintptr_t* const, const size_t); 44800b99b8Sopenharmony_ciint (*g_parseArkFileInfoFn)(uintptr_t, uintptr_t, uintptr_t, const char*, uintptr_t, JsFunction*); 45800b99b8Sopenharmony_ciint (*g_parseArkFrameInfoLocalFn)(uintptr_t, uintptr_t, uintptr_t, uintptr_t, JsFunction*); 46800b99b8Sopenharmony_ciint (*g_parseArkFrameInfoFn)(uintptr_t, uintptr_t, uintptr_t, uintptr_t, uint8_t*, uint64_t, uintptr_t, JsFunction*); 47800b99b8Sopenharmony_ciint (*g_translateArkFrameInfoFn)(uint8_t*, uint64_t, JsFunction*); 48800b99b8Sopenharmony_ciint (*g_arkCreateJsSymbolExtractorFn)(uintptr_t*); 49800b99b8Sopenharmony_ciint (*g_arkDestoryJsSymbolExtractorFn)(uintptr_t); 50800b99b8Sopenharmony_ciint (*g_arkDestoryLocalFn)(); 51800b99b8Sopenharmony_ci 52800b99b8Sopenharmony_cibool GetLibArkHandle() 53800b99b8Sopenharmony_ci{ 54800b99b8Sopenharmony_ci if (g_handle != nullptr) { 55800b99b8Sopenharmony_ci return true; 56800b99b8Sopenharmony_ci } 57800b99b8Sopenharmony_ci g_handle = dlopen(ARK_LIB_NAME, RTLD_LAZY); 58800b99b8Sopenharmony_ci if (g_handle == nullptr) { 59800b99b8Sopenharmony_ci DFXLOGU("Failed to load library(%{public}s).", dlerror()); 60800b99b8Sopenharmony_ci return false; 61800b99b8Sopenharmony_ci } 62800b99b8Sopenharmony_ci return true; 63800b99b8Sopenharmony_ci} 64800b99b8Sopenharmony_ci} 65800b99b8Sopenharmony_ci 66800b99b8Sopenharmony_ci#define DLSYM_ARK_FUNC(funcName, dlsymFuncName) { \ 67800b99b8Sopenharmony_ci pthread_mutex_lock(&g_mutex); \ 68800b99b8Sopenharmony_ci do { \ 69800b99b8Sopenharmony_ci if ((dlsymFuncName) != nullptr) { \ 70800b99b8Sopenharmony_ci break; \ 71800b99b8Sopenharmony_ci } \ 72800b99b8Sopenharmony_ci if (!GetLibArkHandle()) { \ 73800b99b8Sopenharmony_ci break; \ 74800b99b8Sopenharmony_ci } \ 75800b99b8Sopenharmony_ci (dlsymFuncName) = reinterpret_cast<decltype(dlsymFuncName)>(dlsym(g_handle, (funcName))); \ 76800b99b8Sopenharmony_ci if ((dlsymFuncName) == nullptr) { \ 77800b99b8Sopenharmony_ci DFXLOGE("Failed to dlsym(%{public}s), error: %{public}s", (funcName), dlerror()); \ 78800b99b8Sopenharmony_ci break; \ 79800b99b8Sopenharmony_ci } \ 80800b99b8Sopenharmony_ci } while (false); \ 81800b99b8Sopenharmony_ci pthread_mutex_unlock(&g_mutex); \ 82800b99b8Sopenharmony_ci} 83800b99b8Sopenharmony_ci 84800b99b8Sopenharmony_ciint DfxArk::ArkCreateJsSymbolExtractor(uintptr_t* extractorPtr) 85800b99b8Sopenharmony_ci{ 86800b99b8Sopenharmony_ci if (g_arkCreateJsSymbolExtractorFn != nullptr) { 87800b99b8Sopenharmony_ci return g_arkCreateJsSymbolExtractorFn(extractorPtr); 88800b99b8Sopenharmony_ci } 89800b99b8Sopenharmony_ci 90800b99b8Sopenharmony_ci const char* arkFuncName = "ark_create_js_symbol_extractor"; 91800b99b8Sopenharmony_ci DLSYM_ARK_FUNC(arkFuncName, g_arkCreateJsSymbolExtractorFn) 92800b99b8Sopenharmony_ci 93800b99b8Sopenharmony_ci if (g_arkCreateJsSymbolExtractorFn != nullptr) { 94800b99b8Sopenharmony_ci return g_arkCreateJsSymbolExtractorFn(extractorPtr); 95800b99b8Sopenharmony_ci } 96800b99b8Sopenharmony_ci return -1; 97800b99b8Sopenharmony_ci} 98800b99b8Sopenharmony_ci 99800b99b8Sopenharmony_ciint DfxArk::ArkDestoryJsSymbolExtractor(uintptr_t extractorPtr) 100800b99b8Sopenharmony_ci{ 101800b99b8Sopenharmony_ci if (g_arkDestoryJsSymbolExtractorFn != nullptr) { 102800b99b8Sopenharmony_ci return g_arkDestoryJsSymbolExtractorFn(extractorPtr); 103800b99b8Sopenharmony_ci } 104800b99b8Sopenharmony_ci 105800b99b8Sopenharmony_ci const char* arkFuncName = "ark_destory_js_symbol_extractor"; 106800b99b8Sopenharmony_ci DLSYM_ARK_FUNC(arkFuncName, g_arkDestoryJsSymbolExtractorFn) 107800b99b8Sopenharmony_ci 108800b99b8Sopenharmony_ci if (g_arkDestoryJsSymbolExtractorFn != nullptr) { 109800b99b8Sopenharmony_ci return g_arkDestoryJsSymbolExtractorFn(extractorPtr); 110800b99b8Sopenharmony_ci } 111800b99b8Sopenharmony_ci return -1; 112800b99b8Sopenharmony_ci} 113800b99b8Sopenharmony_ci 114800b99b8Sopenharmony_ciint DfxArk::ArkDestoryLocal() 115800b99b8Sopenharmony_ci{ 116800b99b8Sopenharmony_ci if (g_arkDestoryLocalFn != nullptr) { 117800b99b8Sopenharmony_ci return g_arkDestoryLocalFn(); 118800b99b8Sopenharmony_ci } 119800b99b8Sopenharmony_ci 120800b99b8Sopenharmony_ci if (g_handle == nullptr) { 121800b99b8Sopenharmony_ci return -1; 122800b99b8Sopenharmony_ci } 123800b99b8Sopenharmony_ci const char* arkFuncName = "ark_destory_local"; 124800b99b8Sopenharmony_ci pthread_mutex_lock(&g_mutex); 125800b99b8Sopenharmony_ci if (g_arkDestoryLocalFn != nullptr) { 126800b99b8Sopenharmony_ci pthread_mutex_unlock(&g_mutex); 127800b99b8Sopenharmony_ci return g_arkDestoryLocalFn(); 128800b99b8Sopenharmony_ci } 129800b99b8Sopenharmony_ci g_arkDestoryLocalFn = reinterpret_cast<decltype(g_arkDestoryLocalFn)>(dlsym(g_handle, arkFuncName)); 130800b99b8Sopenharmony_ci pthread_mutex_unlock(&g_mutex); 131800b99b8Sopenharmony_ci if (g_arkDestoryLocalFn != nullptr) { 132800b99b8Sopenharmony_ci return g_arkDestoryLocalFn(); 133800b99b8Sopenharmony_ci } 134800b99b8Sopenharmony_ci return -1; 135800b99b8Sopenharmony_ci} 136800b99b8Sopenharmony_ci 137800b99b8Sopenharmony_ciint DfxArk::ParseArkFileInfo(uintptr_t byteCodePc, uintptr_t methodid, uintptr_t mapBase, const char* name, 138800b99b8Sopenharmony_ci uintptr_t extractorPtr, JsFunction *jsFunction) 139800b99b8Sopenharmony_ci{ 140800b99b8Sopenharmony_ci if (g_parseArkFileInfoFn != nullptr) { 141800b99b8Sopenharmony_ci return g_parseArkFileInfoFn(byteCodePc, methodid, mapBase, name, extractorPtr, jsFunction); 142800b99b8Sopenharmony_ci } 143800b99b8Sopenharmony_ci 144800b99b8Sopenharmony_ci const char* arkFuncName = "ark_parse_js_file_info"; 145800b99b8Sopenharmony_ci DLSYM_ARK_FUNC(arkFuncName, g_parseArkFileInfoFn) 146800b99b8Sopenharmony_ci 147800b99b8Sopenharmony_ci if (g_parseArkFileInfoFn != nullptr) { 148800b99b8Sopenharmony_ci return g_parseArkFileInfoFn(byteCodePc, methodid, mapBase, name, extractorPtr, jsFunction); 149800b99b8Sopenharmony_ci } 150800b99b8Sopenharmony_ci return -1; 151800b99b8Sopenharmony_ci} 152800b99b8Sopenharmony_ci 153800b99b8Sopenharmony_ciint DfxArk::ParseArkFrameInfoLocal(uintptr_t byteCodePc, uintptr_t methodid, uintptr_t mapBase, 154800b99b8Sopenharmony_ci uintptr_t offset, JsFunction *jsFunction) 155800b99b8Sopenharmony_ci{ 156800b99b8Sopenharmony_ci if (g_parseArkFrameInfoLocalFn != nullptr) { 157800b99b8Sopenharmony_ci return g_parseArkFrameInfoLocalFn(byteCodePc, methodid, mapBase, offset, jsFunction); 158800b99b8Sopenharmony_ci } 159800b99b8Sopenharmony_ci 160800b99b8Sopenharmony_ci const char* arkFuncName = "ark_parse_js_frame_info_local"; 161800b99b8Sopenharmony_ci DLSYM_ARK_FUNC(arkFuncName, g_parseArkFrameInfoLocalFn) 162800b99b8Sopenharmony_ci 163800b99b8Sopenharmony_ci if (g_parseArkFrameInfoLocalFn != nullptr) { 164800b99b8Sopenharmony_ci return g_parseArkFrameInfoLocalFn(byteCodePc, methodid, mapBase, offset, jsFunction); 165800b99b8Sopenharmony_ci } 166800b99b8Sopenharmony_ci return -1; 167800b99b8Sopenharmony_ci} 168800b99b8Sopenharmony_ci 169800b99b8Sopenharmony_ciint DfxArk::ParseArkFrameInfo(uintptr_t byteCodePc, uintptr_t mapBase, uintptr_t loadOffset, 170800b99b8Sopenharmony_ci uint8_t *data, uint64_t dataSize, uintptr_t extractorPtr, JsFunction *jsFunction) 171800b99b8Sopenharmony_ci{ 172800b99b8Sopenharmony_ci return ParseArkFrameInfo(byteCodePc, 0, mapBase, loadOffset, data, dataSize, extractorPtr, jsFunction); 173800b99b8Sopenharmony_ci} 174800b99b8Sopenharmony_ci 175800b99b8Sopenharmony_ciint DfxArk::ParseArkFrameInfo(uintptr_t byteCodePc, uintptr_t methodid, uintptr_t mapBase, uintptr_t loadOffset, 176800b99b8Sopenharmony_ci uint8_t *data, uint64_t dataSize, uintptr_t extractorPtr, JsFunction *jsFunction) 177800b99b8Sopenharmony_ci{ 178800b99b8Sopenharmony_ci if (g_parseArkFrameInfoFn != nullptr) { 179800b99b8Sopenharmony_ci return g_parseArkFrameInfoFn(byteCodePc, methodid, mapBase, loadOffset, data, dataSize, 180800b99b8Sopenharmony_ci extractorPtr, jsFunction); 181800b99b8Sopenharmony_ci } 182800b99b8Sopenharmony_ci 183800b99b8Sopenharmony_ci const char* arkFuncName = "ark_parse_js_frame_info"; 184800b99b8Sopenharmony_ci DLSYM_ARK_FUNC(arkFuncName, g_parseArkFrameInfoFn) 185800b99b8Sopenharmony_ci 186800b99b8Sopenharmony_ci if (g_parseArkFrameInfoFn != nullptr) { 187800b99b8Sopenharmony_ci return g_parseArkFrameInfoFn(byteCodePc, methodid, mapBase, loadOffset, data, dataSize, 188800b99b8Sopenharmony_ci extractorPtr, jsFunction); 189800b99b8Sopenharmony_ci } 190800b99b8Sopenharmony_ci return -1; 191800b99b8Sopenharmony_ci} 192800b99b8Sopenharmony_ci 193800b99b8Sopenharmony_ciint DfxArk::TranslateArkFrameInfo(uint8_t *data, uint64_t dataSize, JsFunction *jsFunction) 194800b99b8Sopenharmony_ci{ 195800b99b8Sopenharmony_ci if (g_translateArkFrameInfoFn != nullptr) { 196800b99b8Sopenharmony_ci return g_translateArkFrameInfoFn(data, dataSize, jsFunction); 197800b99b8Sopenharmony_ci } 198800b99b8Sopenharmony_ci 199800b99b8Sopenharmony_ci const char* arkFuncName = "ark_translate_js_frame_info"; 200800b99b8Sopenharmony_ci DLSYM_ARK_FUNC(arkFuncName, g_translateArkFrameInfoFn) 201800b99b8Sopenharmony_ci 202800b99b8Sopenharmony_ci if (g_translateArkFrameInfoFn != nullptr) { 203800b99b8Sopenharmony_ci return g_translateArkFrameInfoFn(data, dataSize, jsFunction); 204800b99b8Sopenharmony_ci } 205800b99b8Sopenharmony_ci return -1; 206800b99b8Sopenharmony_ci} 207800b99b8Sopenharmony_ci 208800b99b8Sopenharmony_ciint DfxArk::StepArkFrame(void *obj, OHOS::HiviewDFX::ReadMemFunc readMemFn, 209800b99b8Sopenharmony_ci uintptr_t *fp, uintptr_t *sp, uintptr_t *pc, uintptr_t* methodid, bool *isJsFrame) 210800b99b8Sopenharmony_ci{ 211800b99b8Sopenharmony_ci if (g_stepArkFn != nullptr) { 212800b99b8Sopenharmony_ci return g_stepArkFn(obj, readMemFn, fp, sp, pc, methodid, isJsFrame); 213800b99b8Sopenharmony_ci } 214800b99b8Sopenharmony_ci 215800b99b8Sopenharmony_ci const char* arkFuncName = "step_ark"; 216800b99b8Sopenharmony_ci DLSYM_ARK_FUNC(arkFuncName, g_stepArkFn) 217800b99b8Sopenharmony_ci 218800b99b8Sopenharmony_ci if (g_stepArkFn != nullptr) { 219800b99b8Sopenharmony_ci return g_stepArkFn(obj, readMemFn, fp, sp, pc, methodid, isJsFrame); 220800b99b8Sopenharmony_ci } 221800b99b8Sopenharmony_ci return -1; 222800b99b8Sopenharmony_ci} 223800b99b8Sopenharmony_ci 224800b99b8Sopenharmony_ciint DfxArk::StepArkFrameWithJit(OHOS::HiviewDFX::ArkUnwindParam* arkPrama) 225800b99b8Sopenharmony_ci{ 226800b99b8Sopenharmony_ci if (g_stepArkWithJitFn != nullptr) { 227800b99b8Sopenharmony_ci return g_stepArkWithJitFn(arkPrama); 228800b99b8Sopenharmony_ci } 229800b99b8Sopenharmony_ci 230800b99b8Sopenharmony_ci const char* const arkFuncName = "step_ark_with_record_jit"; 231800b99b8Sopenharmony_ci DLSYM_ARK_FUNC(arkFuncName, g_stepArkWithJitFn) 232800b99b8Sopenharmony_ci 233800b99b8Sopenharmony_ci if (g_stepArkWithJitFn != nullptr) { 234800b99b8Sopenharmony_ci return g_stepArkWithJitFn(arkPrama); 235800b99b8Sopenharmony_ci } 236800b99b8Sopenharmony_ci return -1; 237800b99b8Sopenharmony_ci} 238800b99b8Sopenharmony_ci 239800b99b8Sopenharmony_ciint DfxArk::JitCodeWriteFile(void* ctx, OHOS::HiviewDFX::ReadMemFunc readMemFn, int fd, 240800b99b8Sopenharmony_ci const uintptr_t* const jitCodeArray, const size_t jitSize) 241800b99b8Sopenharmony_ci{ 242800b99b8Sopenharmony_ci if (g_jitCodeWriteFileFn != nullptr) { 243800b99b8Sopenharmony_ci return g_jitCodeWriteFileFn(ctx, readMemFn, fd, jitCodeArray, jitSize); 244800b99b8Sopenharmony_ci } 245800b99b8Sopenharmony_ci 246800b99b8Sopenharmony_ci const char* const arkFuncName = "ark_write_jit_code"; 247800b99b8Sopenharmony_ci DLSYM_ARK_FUNC(arkFuncName, g_jitCodeWriteFileFn) 248800b99b8Sopenharmony_ci 249800b99b8Sopenharmony_ci if (g_jitCodeWriteFileFn != nullptr) { 250800b99b8Sopenharmony_ci return g_jitCodeWriteFileFn(ctx, readMemFn, fd, jitCodeArray, jitSize); 251800b99b8Sopenharmony_ci } 252800b99b8Sopenharmony_ci return -1; 253800b99b8Sopenharmony_ci} 254800b99b8Sopenharmony_ci 255800b99b8Sopenharmony_ciint DfxArk::GetArkNativeFrameInfo(int pid, uintptr_t& pc, uintptr_t& fp, uintptr_t& sp, JsFrame* frames, size_t& size) 256800b99b8Sopenharmony_ci{ 257800b99b8Sopenharmony_ci if (g_getArkNativeFrameInfoFn != nullptr) { 258800b99b8Sopenharmony_ci return g_getArkNativeFrameInfoFn(pid, &pc, &fp, &sp, frames, size); 259800b99b8Sopenharmony_ci } 260800b99b8Sopenharmony_ci 261800b99b8Sopenharmony_ci const char* arkFuncName = "get_ark_native_frame_info"; 262800b99b8Sopenharmony_ci DLSYM_ARK_FUNC(arkFuncName, g_getArkNativeFrameInfoFn) 263800b99b8Sopenharmony_ci 264800b99b8Sopenharmony_ci if (g_getArkNativeFrameInfoFn != nullptr) { 265800b99b8Sopenharmony_ci return g_getArkNativeFrameInfoFn(pid, &pc, &fp, &sp, frames, size); 266800b99b8Sopenharmony_ci } 267800b99b8Sopenharmony_ci return -1; 268800b99b8Sopenharmony_ci} 269800b99b8Sopenharmony_ci} // namespace HiviewDFX 270800b99b8Sopenharmony_ci} // namespace OHOS 271