• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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