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 }