1 /*
2 * Copyright (c) 2025 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_jsvm.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 "DfxJsvm"
35
36 const char* const JSVM_LIB_NAME = "libjsvm.so";
37 }
38
GetLibJsvmHandle()39 bool DfxJsvm::GetLibJsvmHandle()
40 {
41 if (handle_ != nullptr) {
42 return true;
43 }
44 handle_ = dlopen(JSVM_LIB_NAME, RTLD_LAZY);
45 if (handle_ == nullptr) {
46 DFXLOGU("Failed to load library(%{public}s).", dlerror());
47 return false;
48 }
49 return true;
50 }
51
Instance()52 DfxJsvm& DfxJsvm::Instance()
53 {
54 static DfxJsvm instance;
55 return instance;
56 }
57
58 template <typename FuncName>
DlsymJsvmFunc(const char * funcName,FuncName & dlsymFuncName)59 void DfxJsvm::DlsymJsvmFunc(const char* funcName, FuncName& dlsymFuncName)
60 {
61 std::unique_lock<std::mutex> lock(mutex_);
62 do {
63 if (dlsymFuncName != nullptr) {
64 break;
65 }
66 if (!GetLibJsvmHandle()) {
67 break;
68 }
69 (dlsymFuncName) = reinterpret_cast<FuncName>(dlsym(handle_, (funcName)));
70 if (dlsymFuncName == nullptr) {
71 DFXLOGE("Failed to dlsym(%{public}s), error: %{public}s", funcName, dlerror());
72 break;
73 }
74 } while (false);
75 }
76
JsvmCreateJsSymbolExtractor(uintptr_t * extractorPtr,uint32_t pid)77 int DfxJsvm::JsvmCreateJsSymbolExtractor(uintptr_t* extractorPtr, uint32_t pid)
78 {
79 if (jsvmCreateJsSymbolExtractorFn_ != nullptr) {
80 return jsvmCreateJsSymbolExtractorFn_(extractorPtr, pid);
81 }
82
83 const char* jsvmFuncName = "create_jsvm_extractor";
84 DlsymJsvmFunc(jsvmFuncName, jsvmCreateJsSymbolExtractorFn_);
85
86 if (jsvmCreateJsSymbolExtractorFn_ != nullptr) {
87 return jsvmCreateJsSymbolExtractorFn_(extractorPtr, pid);
88 }
89 return -1;
90 }
91
JsvmDestroyJsSymbolExtractor(uintptr_t extractorPtr)92 int DfxJsvm::JsvmDestroyJsSymbolExtractor(uintptr_t extractorPtr)
93 {
94 if (jsvmDestroyJsSymbolExtractorFn_ != nullptr) {
95 return jsvmDestroyJsSymbolExtractorFn_(extractorPtr);
96 }
97
98 const char* jsvmFuncName = "destroy_jsvm_extractor";
99 DlsymJsvmFunc(jsvmFuncName, jsvmDestroyJsSymbolExtractorFn_);
100
101 if (jsvmDestroyJsSymbolExtractorFn_ != nullptr) {
102 return jsvmDestroyJsSymbolExtractorFn_(extractorPtr);
103 }
104 return -1;
105 }
106
ParseJsvmFrameInfo(uintptr_t pc,uintptr_t extractorPtr,JsvmFunction * jsvmFunction)107 int DfxJsvm::ParseJsvmFrameInfo(uintptr_t pc, uintptr_t extractorPtr, JsvmFunction *jsvmFunction)
108 {
109 if (parseJsvmFrameInfoFn_ != nullptr && jsvmFunction != nullptr) {
110 return parseJsvmFrameInfoFn_(pc, extractorPtr, jsvmFunction);
111 }
112
113 const char* jsvmFuncName = "jsvm_parse_js_frame_info";
114 DlsymJsvmFunc(jsvmFuncName, parseJsvmFrameInfoFn_);
115
116 if (parseJsvmFrameInfoFn_ != nullptr && jsvmFunction != nullptr) {
117 return parseJsvmFrameInfoFn_(pc, extractorPtr, jsvmFunction);
118 }
119 return -1;
120 }
121
StepJsvmFrame(void * obj,ReadMemFunc readMemFn,JsvmStepParam * jsvmParam)122 int DfxJsvm::StepJsvmFrame(void *obj, ReadMemFunc readMemFn, JsvmStepParam* jsvmParam)
123 {
124 if (obj == nullptr || readMemFn == nullptr || jsvmParam == nullptr) {
125 DFXLOGE("param is nullptr.");
126 return -1;
127 }
128 if (stepJsvmFn_ != nullptr) {
129 return stepJsvmFn_(obj, readMemFn, jsvmParam);
130 }
131
132 const char* jsvmFuncName = "step_jsvm";
133 DlsymJsvmFunc(jsvmFuncName, stepJsvmFn_);
134
135 if (stepJsvmFn_ != nullptr) {
136 return stepJsvmFn_(obj, readMemFn, jsvmParam);
137 }
138 return -1;
139 }
140 } // namespace HiviewDFX
141 } // namespace OHOS
142