1 /*
2  * Copyright (c) 2024 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 #include <gtest/gtest.h>
16 
17 #include <cstdio>
18 #include <dlfcn.h>
19 #include <cstdint>
20 
21 #include "dfx_ark.h"
22 #include "dfx_log.h"
23 
24 using namespace testing;
25 using namespace testing::ext;
26 using namespace std;
27 
28 namespace OHOS {
29 namespace HiviewDFX {
30 namespace {
31 const char ARK_LIB_NAME[] = "libark_jsruntime.so";
32 
33 void* g_handle = nullptr;
34 pthread_mutex_t g_mutex;
35 int (*g_getArkNativeFrameInfoFn)(int, uintptr_t*, uintptr_t*, uintptr_t*, JsFrame*, size_t&);
36 int (*g_stepArkFn)(void*, OHOS::HiviewDFX::ReadMemFunc, uintptr_t*, uintptr_t*, uintptr_t*, uintptr_t*, bool*);
37 int (*g_stepArkWithJitFn)(OHOS::HiviewDFX::ArkUnwindParam*);
38 int (*g_jitCodeWriteFileFn)(void*, OHOS::HiviewDFX::ReadMemFunc, int, const uintptr_t* const, const size_t);
39 int (*g_parseArkFileInfoFn)(uintptr_t, uintptr_t, uintptr_t, const char*, uintptr_t, JsFunction*);
40 int (*g_parseArkFrameInfoLocalFn)(uintptr_t, uintptr_t, uintptr_t, uintptr_t, JsFunction*);
41 int (*g_parseArkFrameInfoFn)(uintptr_t, uintptr_t, uintptr_t, uintptr_t, uint8_t*, uint64_t, uintptr_t, JsFunction*);
42 int (*g_arkCreateJsSymbolExtractorFn)(uintptr_t*);
43 int (*g_arkDestoryJsSymbolExtractorFn)(uintptr_t);
44 using RustDemangleFn = char*(*)(const char *);
45 RustDemangleFn g_rustDemangleFn = nullptr;
46 
GetLibArkHandle()47 bool GetLibArkHandle()
48 {
49     if (g_handle != nullptr) {
50         return true;
51     }
52     g_handle = dlopen(ARK_LIB_NAME, RTLD_LAZY);
53     if (g_handle == nullptr) {
54         LOGU("Failed to load library(%s).", dlerror());
55         return false;
56     }
57     return true;
58 }
59 } // namespace
60 
61 #define DLSYM_ARK_FUNC(FuncName, DlsymFuncName) { \
62     pthread_mutex_lock(&g_mutex); \
63     do { \
64         if (!GetLibArkHandle()) { \
65             break; \
66         } \
67         *reinterpret_cast<void**>(&(DlsymFuncName)) = dlsym(g_handle, (FuncName)); \
68     } while (false); \
69     pthread_mutex_unlock(&g_mutex); \
70 }
71 
72 class ArkTest : public testing::Test {
73 public:
SetUpTestCase()74     static void SetUpTestCase() {}
TearDownTestCase()75     static void TearDownTestCase() {}
SetUp()76     void SetUp() {}
TearDown()77     void TearDown() {}
78 };
79 
80 /**
81  * @tc.name: ArkTest001
82  * @tc.desc: test ArkCreateJsSymbolExtractor functions
83  * @tc.type: FUNC
84  */
85 HWTEST_F(ArkTest, ArkTest001, TestSize.Level2)
86 {
87     GTEST_LOG_(INFO) << "ArkTest001: start.";
88     uintptr_t zero = 0;
89     uintptr_t* extractorPtr = &zero;
90     const char* arkFuncName = "ark_create_js_symbol_extractor";
91     DLSYM_ARK_FUNC(arkFuncName, g_arkCreateJsSymbolExtractorFn)
92     ASSERT_NE(g_arkCreateJsSymbolExtractorFn, nullptr);
93     g_arkCreateJsSymbolExtractorFn(extractorPtr);
94     g_arkCreateJsSymbolExtractorFn = nullptr;
95     GTEST_LOG_(INFO) << "ArkTest001: end.";
96 }
97 
98 /**
99  * @tc.name: ArkTest002
100  * @tc.desc: test ArkDestoryJsSymbolExtractor functions
101  * @tc.type: FUNC
102  */
103 HWTEST_F(ArkTest, ArkTest002, TestSize.Level2)
104 {
105     GTEST_LOG_(INFO) << "ArkTest002: start.";
106     uintptr_t extractorPtr = 0;
107     const char* arkFuncName = "ark_destory_js_symbol_extractor";
108     DLSYM_ARK_FUNC(arkFuncName, g_arkDestoryJsSymbolExtractorFn)
109     ASSERT_NE(g_arkDestoryJsSymbolExtractorFn, nullptr);
110     g_arkDestoryJsSymbolExtractorFn(extractorPtr);
111     g_arkDestoryJsSymbolExtractorFn = nullptr;
112     GTEST_LOG_(INFO) << "ArkTest002: end.";
113 }
114 
115 /**
116  * @tc.name: ArkTest003
117  * @tc.desc: test ParseArkFileInfo functions
118  * @tc.type: FUNC
119  */
120 HWTEST_F(ArkTest, ArkTest003, TestSize.Level2)
121 {
122     GTEST_LOG_(INFO) << "ArkTest003: start.";
123     uintptr_t byteCodePc = 0;
124     uintptr_t methodid = 0;
125     uintptr_t mapBase = 0;
126     const char* name = nullptr;
127     uintptr_t extractorPtr = 0;
128     JsFunction *jsFunction = nullptr;
129     const char* arkFuncName = "ark_parse_js_file_info";
130     DLSYM_ARK_FUNC(arkFuncName, g_parseArkFileInfoFn)
131     ASSERT_NE(g_parseArkFileInfoFn, nullptr);
132     g_parseArkFileInfoFn(byteCodePc, methodid, mapBase, name, extractorPtr, jsFunction);
133     g_parseArkFileInfoFn = nullptr;
134     GTEST_LOG_(INFO) << "ArkTest003: end.";
135 }
136 
137 /**
138  * @tc.name: ArkTest004
139  * @tc.desc: test ParseArkFrameInfoLocal functions
140  * @tc.type: FUNC
141  */
142 HWTEST_F(ArkTest, ArkTest004, TestSize.Level2)
143 {
144     GTEST_LOG_(INFO) << "ArkTest004: start.";
145     uintptr_t byteCodePc = 0;
146     uintptr_t methodid = 0;
147     uintptr_t mapBase = 0;
148     uintptr_t offset = 0;
149     JsFunction *jsFunction = nullptr;
150     const char* arkFuncName = "ark_parse_js_frame_info_local";
151     DLSYM_ARK_FUNC(arkFuncName, g_parseArkFrameInfoLocalFn)
152     ASSERT_NE(g_parseArkFrameInfoLocalFn, nullptr);
153     g_parseArkFrameInfoLocalFn(byteCodePc, methodid, mapBase, offset, jsFunction);
154     g_parseArkFrameInfoLocalFn = nullptr;
155     GTEST_LOG_(INFO) << "ArkTest004: end.";
156 }
157 
158 /**
159  * @tc.name: ArkTest005
160  * @tc.desc: test ParseArkFrameInfo functions
161  * @tc.type: FUNC
162  */
163 HWTEST_F(ArkTest, ArkTest005, TestSize.Level2)
164 {
165     GTEST_LOG_(INFO) << "ArkTest005: start.";
166     uintptr_t byteCodePc = 0;
167     uintptr_t methodid = 0;
168     uintptr_t mapBase = 0;
169     uintptr_t loadOffset = 0;
170     uint8_t *data = nullptr;
171     uint64_t dataSize = 0;
172     uintptr_t extractorPtr = 0;
173     JsFunction *jsFunction = nullptr;
174     const char* arkFuncName = "ark_parse_js_frame_info";
175     DLSYM_ARK_FUNC(arkFuncName, g_parseArkFrameInfoFn)
176     ASSERT_NE(g_parseArkFrameInfoFn, nullptr);
177     g_parseArkFrameInfoFn(byteCodePc, methodid, mapBase, loadOffset, data, dataSize, extractorPtr, jsFunction);
178     g_parseArkFrameInfoFn = nullptr;
179     GTEST_LOG_(INFO) << "ArkTest005: end.";
180 }
181 
182 /**
183  * @tc.name: ArkTest006
184  * @tc.desc: test StepArkFrame functions
185  * @tc.type: FUNC
186  */
187 HWTEST_F(ArkTest, ArkTest006, TestSize.Level2)
188 {
189     GTEST_LOG_(INFO) << "ArkTest006: start.";
190     uintptr_t zero = 0;
191     void *obj = nullptr;
192     OHOS::HiviewDFX::ReadMemFunc readMemFn = nullptr;
193     uintptr_t *fp = &zero;
194     uintptr_t *sp = &zero;
195     uintptr_t *pc = &zero;
196     uintptr_t* methodid = &zero;
197     bool *isJsFrame = nullptr;
198     const char* arkFuncName = "step_ark";
199     DLSYM_ARK_FUNC(arkFuncName, g_stepArkFn)
200     ASSERT_NE(g_stepArkFn, nullptr);
201     g_stepArkFn(obj, readMemFn, fp, sp, pc, methodid, isJsFrame);
202     g_stepArkFn = nullptr;
203     GTEST_LOG_(INFO) << "ArkTest006: end.";
204 }
205 
206 /**
207  * @tc.name: ArkTest007
208  * @tc.desc: test StepArkFrameWithJit functions
209  * @tc.type: FUNC
210  */
211 HWTEST_F(ArkTest, ArkTest007, TestSize.Level2)
212 {
213     GTEST_LOG_(INFO) << "ArkTest007: start.";
214     uintptr_t zero = 0;
215     void *ctx = &zero;
216     ReadMemFunc readMem = nullptr;
217     uintptr_t *fp = &zero;
218     uintptr_t *sp = &zero;
219     uintptr_t *pc = &zero;
220     uintptr_t *methodId = &zero;
221     bool *isJsFrame = nullptr;
222     std::vector<uintptr_t> vec;
223     std::vector<uintptr_t>& jitCache = vec;
224     OHOS::HiviewDFX::ArkUnwindParam ark(ctx, readMem, fp, sp, pc, methodId, isJsFrame, jitCache);
225     OHOS::HiviewDFX::ArkUnwindParam* arkPrama = &ark;
226     const char* const arkFuncName = "step_ark_with_record_jit";
227     DLSYM_ARK_FUNC(arkFuncName, g_stepArkWithJitFn)
228     ASSERT_NE(g_stepArkWithJitFn, nullptr);
229     g_stepArkWithJitFn(arkPrama);
230     g_stepArkWithJitFn = nullptr;
231     GTEST_LOG_(INFO) << "ArkTest007: end.";
232 }
233 
234 /**
235  * @tc.name: ArkTest008
236  * @tc.desc: test JitCodeWriteFile functions
237  * @tc.type: FUNC
238  */
239 HWTEST_F(ArkTest, ArkTest008, TestSize.Level2)
240 {
241     GTEST_LOG_(INFO) << "ArkTest008: start.";
242     void* ctx = nullptr;
243     OHOS::HiviewDFX::ReadMemFunc readMemFn = nullptr;
244     int fd = -1;
245     const uintptr_t* const jitCodeArray = nullptr;
246     const size_t jitSize = 0;
247     const char* const arkFuncName = "ark_write_jit_code";
248     DLSYM_ARK_FUNC(arkFuncName, g_jitCodeWriteFileFn)
249     ASSERT_NE(g_jitCodeWriteFileFn, nullptr);
250     g_jitCodeWriteFileFn(ctx, readMemFn, fd, jitCodeArray, jitSize);
251     g_jitCodeWriteFileFn = nullptr;
252     GTEST_LOG_(INFO) << "ArkTest008: end.";
253 }
254 
255 /**
256  * @tc.name: ArkTest009
257  * @tc.desc: test GetArkNativeFrameInfo functions
258  * @tc.type: FUNC
259  */
260 HWTEST_F(ArkTest, ArkTest009, TestSize.Level2)
261 {
262     GTEST_LOG_(INFO) << "ArkTest009: start.";
263     int pid = 0;
264     uintptr_t zero = 0;
265     uintptr_t& pc = zero;
266     uintptr_t& fp = zero;
267     uintptr_t& sp = zero;
268     JsFrame* frames = nullptr;
269     size_t& size = zero;
270     const char* arkFuncName = "get_ark_native_frame_info";
271     DLSYM_ARK_FUNC(arkFuncName, g_getArkNativeFrameInfoFn)
272     ASSERT_NE(g_getArkNativeFrameInfoFn, nullptr);
273     g_getArkNativeFrameInfoFn(pid, &pc, &fp, &sp, frames, size);
274     g_getArkNativeFrameInfoFn = nullptr;
275     GTEST_LOG_(INFO) << "ArkTest009: end.";
276 }
277 
278 /**
279  * @tc.name: ArkTest010
280  * @tc.desc: test rustc_demangle functions
281  * @tc.type: FUNC
282  */
283 HWTEST_F(ArkTest, ArkTest010, TestSize.Level2)
284 {
285     GTEST_LOG_(INFO) << "ArkTest010: start.";
286     void* handle = dlopen("librustc_demangle.z.so", RTLD_LAZY | RTLD_NODELETE);
287     ASSERT_TRUE(handle) << "Failed to dlopen librustc_demangle";
288     g_rustDemangleFn = (RustDemangleFn)dlsym(handle, "rustc_demangle");
289     ASSERT_TRUE(g_rustDemangleFn) << "Failed to dlsym rustc_demangle";
290     std::string reason = "reason";
291     const char *bufStr = reason.c_str();
292     g_rustDemangleFn(bufStr);
293     g_rustDemangleFn = nullptr;
294     GTEST_LOG_(INFO) << "ArkTest010: end.";
295 }
296 }
297 }