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
16 #include <cstdio>
17
18 #include "assembler/assembly-emitter.h"
19 #include "assembler/assembly-parser.h"
20 #include "libpandafile/class_data_accessor-inl.h"
21 #include "libziparchive/zip_archive.h"
22 #include "ecmascript/dfx/stackinfo/js_stackinfo.h"
23 #include "ecmascript/tests/test_helper.h"
24
25 using namespace panda::ecmascript;
26
27 namespace panda::test {
28 class JsStackInfoTest : public testing::Test {
29 public:
SetUpTestCase()30 static void SetUpTestCase()
31 {
32 GTEST_LOG_(INFO) << "SetUpTestCase";
33 }
34
TearDownTestCase()35 static void TearDownTestCase()
36 {
37 GTEST_LOG_(INFO) << "TearDownCase";
38 }
39
SetUp()40 void SetUp() override
41 {
42 TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
43 instance->SetEnableForceGC(false);
44 }
45
TearDown()46 void TearDown() override
47 {
48 TestHelper::DestroyEcmaVMWithScope(instance, scope);
49 }
50
51 EcmaVM *instance {nullptr};
52 EcmaHandleScope *scope {nullptr};
53 JSThread *thread {nullptr};
54 };
55
ToUintPtr(FrameType frame)56 uintptr_t ToUintPtr(FrameType frame)
57 {
58 return static_cast<uintptr_t>(frame);
59 }
60
ReadMemFunc(void * ctx,uintptr_t addr,uintptr_t * value)61 bool ReadMemFunc([[maybe_unused]] void *ctx, uintptr_t addr, uintptr_t *value)
62 {
63 *value = *(reinterpret_cast<uintptr_t *>(addr));
64 return true;
65 }
66
67 /**
68 * @tc.name: ArkFrameCheck
69 * @tc.desc: Check whether the result returned through "ArkFrameCheck" function is within expectations.
70 * @tc.type: FUNC
71 * @tc.require:
72 */
HWTEST_F_L0(JsStackInfoTest,TestArkFrameCheck)73 HWTEST_F_L0(JsStackInfoTest, TestArkFrameCheck)
74 {
75 for (uintptr_t i = 0; i < 25; i++) {
76 bool ret = ArkFrameCheck(i);
77 if (i == ToUintPtr(FrameType::OPTIMIZED_ENTRY_FRAME) ||
78 i == ToUintPtr(FrameType::ASM_INTERPRETER_ENTRY_FRAME)) {
79 EXPECT_TRUE(ret == true);
80 } else {
81 EXPECT_TRUE(ret == false);
82 }
83 }
84 }
85
86 /**
87 * @tc.name: IsJsFunctionFrame
88 * @tc.desc: Check whether the result returned through "IsJsFunctionFrame" function is within expectations.
89 * @tc.type: FUNC
90 * @tc.require:
91 */
HWTEST_F_L0(JsStackInfoTest,TestIsJsFunctionFrame)92 HWTEST_F_L0(JsStackInfoTest, TestIsJsFunctionFrame)
93 {
94 for (uintptr_t i = 0; i < 25; i++) {
95 bool ret = IsJsFunctionFrame(i);
96 if (i == ToUintPtr(FrameType::ASM_INTERPRETER_FRAME) ||
97 i == ToUintPtr(FrameType::INTERPRETER_CONSTRUCTOR_FRAME) ||
98 i == ToUintPtr(FrameType::INTERPRETER_FRAME) ||
99 i == ToUintPtr(FrameType::INTERPRETER_FAST_NEW_FRAME)) {
100 EXPECT_TRUE(ret == true);
101 } else {
102 EXPECT_TRUE(ret == false);
103 }
104 }
105 }
106
107 /**
108 * @tc.name: IsFastJitFunctionFrame
109 * @tc.desc: Check whether the result returned through "IsFastJitFunctionFrame" function is within expectations.
110 * @tc.type: FUNC
111 * @tc.require:
112 */
HWTEST_F_L0(JsStackInfoTest,TestIsFastJitFunctionFrame)113 HWTEST_F_L0(JsStackInfoTest, TestIsFastJitFunctionFrame)
114 {
115 for (uintptr_t i = 0; i < 25; i++) {
116 bool ret = IsFastJitFunctionFrame(i);
117 if (i == ToUintPtr(FrameType::FASTJIT_FUNCTION_FRAME) ||
118 i == ToUintPtr(FrameType::FASTJIT_FAST_CALL_FUNCTION_FRAME)) {
119 EXPECT_TRUE(ret == true);
120 } else {
121 EXPECT_TRUE(ret == false);
122 }
123 }
124 }
125
126 /**
127 * @tc.name: IsNativeFunctionFrame
128 * @tc.desc: Check whether the result returned through "IsNativeFunctionFrame" function is within expectations.
129 * @tc.type: FUNC
130 * @tc.require:
131 */
HWTEST_F_L0(JsStackInfoTest,TestIsNativeFunctionFrame)132 HWTEST_F_L0(JsStackInfoTest, TestIsNativeFunctionFrame)
133 {
134 for (uintptr_t i = 0; i < 25; i++) {
135 bool ret = IsNativeFunctionFrame(i);
136 if (i == ToUintPtr(FrameType::OPTIMIZED_FRAME) ||
137 i == ToUintPtr(FrameType::BASELINE_BUILTIN_FRAME) ||
138 i == ToUintPtr(FrameType::ASM_BRIDGE_FRAME) ||
139 i == ToUintPtr(FrameType::OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME) ||
140 i == ToUintPtr(FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME) ||
141 i == ToUintPtr(FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME) ||
142 i == ToUintPtr(FrameType::OPTIMIZED_JS_FUNCTION_FRAME) ||
143 i == ToUintPtr(FrameType::LEAVE_FRAME) ||
144 i == ToUintPtr(FrameType::LEAVE_FRAME_WITH_ARGV) ||
145 i == ToUintPtr(FrameType::BUILTIN_CALL_LEAVE_FRAME) ||
146 i == ToUintPtr(FrameType::BUILTIN_FRAME) ||
147 i == ToUintPtr(FrameType::BUILTIN_ENTRY_FRAME) ||
148 i == ToUintPtr(FrameType::BUILTIN_FRAME_WITH_ARGV) ||
149 i == ToUintPtr(FrameType::BUILTIN_FRAME_WITH_ARGV_STACK_OVER_FLOW_FRAME) ||
150 i == ToUintPtr(FrameType::ASM_INTERPRETER_BRIDGE_FRAME)) {
151 EXPECT_TRUE(ret == true);
152 } else {
153 EXPECT_TRUE(ret == false);
154 }
155 }
156 }
157
158 /**
159 * @tc.name: IsAotFunctionFrame
160 * @tc.desc: Check whether the result returned through "IsAotFunctionFrame" function is within expectations.
161 * @tc.type: FUNC
162 * @tc.require:
163 */
HWTEST_F_L0(JsStackInfoTest,TestIsAotFunctionFrame)164 HWTEST_F_L0(JsStackInfoTest, TestIsAotFunctionFrame)
165 {
166 for (uintptr_t i = 0; i < 25; i++) {
167 bool ret = IsAotFunctionFrame(i);
168 if (i == ToUintPtr(FrameType::OPTIMIZED_JS_FUNCTION_FRAME) ||
169 i == ToUintPtr(FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME)) {
170 EXPECT_TRUE(ret == true);
171 } else {
172 EXPECT_TRUE(ret == false);
173 }
174 }
175 }
176
177 /**
178 * @tc.name: ReadMethodInfo
179 * @tc.desc: Check whether the result returned through "ReadMethodInfo" function is within expectations.
180 * @tc.type: FUNC
181 * @tc.require:
182 */
HWTEST_F_L0(JsStackInfoTest,TestReadMethodInfo)183 HWTEST_F_L0(JsStackInfoTest, TestReadMethodInfo)
184 {
185 const char *filename = "__JSPandaFileManagerTest1.pa";
186 const char *data = R"(
187 .function void foo() {
188 return
189 }
190 )";
191 pandasm::Parser parser;
192 auto res = parser.Parse(data);
193 auto file = pandasm::AsmEmitter::Emit(res.Value());
194 auto jsPandaFile = std::make_shared<JSPandaFile>(file.release(), CString(filename), CreateMode::DFX);
195 EXPECT_TRUE(jsPandaFile != nullptr);
196 CVector<MethodInfo> result;
197 const panda_file::File *pf = jsPandaFile->GetPandaFile();
198 Span<const uint32_t> classIndexes = jsPandaFile->GetClasses();
199 for (const uint32_t index : classIndexes) {
200 panda_file::File::EntityId classId(index);
201 if (jsPandaFile->IsExternal(classId)) {
202 continue;
203 }
204 panda_file::ClassDataAccessor cda(*pf, classId);
205 cda.EnumerateMethods([&result, jsPandaFile](panda_file::MethodDataAccessor &mda) {
206 auto info = JSStackTrace::ReadMethodInfo(mda);
207 if (!info) {
208 return;
209 }
210 result.push_back(info.value());
211 });
212 }
213 EXPECT_TRUE(result.size() > 0);
214 }
215
216 /**
217 * @tc.name: ReadAllMethodInfos
218 * @tc.desc: Check whether the result returned through "ReadAllMethodInfos" function is within expectations.
219 * @tc.type: FUNC
220 * @tc.require:
221 */
HWTEST_F_L0(JsStackInfoTest,TestReadAllMethodInfos)222 HWTEST_F_L0(JsStackInfoTest, TestReadAllMethodInfos)
223 {
224 const char *filename = "__JsStackInfoTest.pa";
225 const char *data = R"(
226 .function void foo() {
227 return
228 }
229 )";
230 pandasm::Parser parser;
231 auto res = parser.Parse(data);
232 auto file = pandasm::AsmEmitter::Emit(res.Value());
233 auto pf = std::make_shared<JSPandaFile>(file.release(), CString(filename), CreateMode::DFX);
234 EXPECT_TRUE(pf != nullptr);
235 auto methods = JSStackTrace::ReadAllMethodInfos(pf);
236 EXPECT_TRUE(methods.size() > 0);
237 pf = nullptr;
238 methods = JSStackTrace::ReadAllMethodInfos(pf);
239 EXPECT_TRUE(methods.size() == 0);
240 }
241
242 /**
243 * @tc.name: TranslateByteCodePc
244 * @tc.desc: Check whether the result returned through "TranslateByteCodePc" function is within expectations.
245 * @tc.type: FUNC
246 * @tc.require:
247 */
HWTEST_F_L0(JsStackInfoTest,TestTranslateByteCodePc)248 HWTEST_F_L0(JsStackInfoTest, TestTranslateByteCodePc)
249 {
250 CVector<MethodInfo> vec = {
251 {0, 0, 24},
252 {1, 24, 30},
253 {2, 54, 56},
254 {3, 110, 60}
255 };
256 uintptr_t realPc = 115;
257
258 auto ret = JSStackTrace::TranslateByteCodePc(realPc, vec);
259 EXPECT_TRUE(ret != std::nullopt);
260
261 vec.clear();
262 ret = JSStackTrace::TranslateByteCodePc(realPc, vec);
263 EXPECT_TRUE(ret == std::nullopt);
264
265 vec.push_back({2, 54, 56});
266 ret = JSStackTrace::TranslateByteCodePc(realPc, vec);
267 EXPECT_TRUE(ret == std::nullopt);
268 }
269
270 /**
271 * @tc.name: ParseJsFrameInfo
272 * @tc.desc: Check whether the result returned through "ParseJsFrameInfo" function is within expectations.
273 * @tc.type: FUNC
274 * @tc.require:
275 */
HWTEST_F_L0(JsStackInfoTest,TestParseJsFrameInfo)276 HWTEST_F_L0(JsStackInfoTest, TestParseJsFrameInfo)
277 {
278 const char *filename = "__JsStackInfoTest.pa";
279 const char *data = R"(
280 .function void foo() {
281 return
282 }
283 )";
284 pandasm::Parser parser;
285 auto res = parser.Parse(data);
286 auto file = pandasm::AsmEmitter::Emit(res.Value());
287 auto jsPandaFile = std::make_shared<JSPandaFile>(file.release(), CString(filename), CreateMode::DFX);
288 EXPECT_TRUE(jsPandaFile != nullptr);
289 auto debugExtractor = std::make_unique<DebugInfoExtractor>(jsPandaFile.get());
290 auto methods = JSStackTrace::ReadAllMethodInfos(jsPandaFile);
291 uintptr_t offset = 0;
292 JsFunction jsFunction;
293 ParseJsFrameInfo(jsPandaFile.get(), debugExtractor.get(), EntityId(methods[0].methodId), offset, jsFunction);
294 EXPECT_TRUE(std::string(jsFunction.functionName) == "foo");
295 }
296
297 /**
298 * @tc.name: ArkParseJsFrameInfo
299 * @tc.desc: Check whether the result returned through "ArkCreateJSSymbolExtractor" function is within expectations;
300 * Check whether the result returned through "ArkParseJsFrameInfo" function is within expectations;
301 * Check whether the result returned through "ArkDestoryJSSymbolExtractor" function is within expectations.
302 * @tc.type: FUNC
303 * @tc.require:
304 */
HWTEST_F_L0(JsStackInfoTest,TestArkParseJsFrameInfo)305 HWTEST_F_L0(JsStackInfoTest, TestArkParseJsFrameInfo)
306 {
307 const char *filename1 = "__JsStackInfoTest1.pa";
308 const char *filename2 = "__JsStackInfoTest2.pa";
309 const char *pfdata1 = R"(
310 .function void foo() {
311 return
312 }
313 )";
314 const char *pfdata2 = R"(
315 .language ECMAScript
316 .function any func_main_0(any a0, any a1, any a2) {
317 ldai 1
318 return
319 }
320 )";
321 pandasm::Parser parser1;
322 pandasm::Parser parser2;
323 auto res1 = parser1.Parse(pfdata1);
324 auto res2 = parser2.Parse(pfdata2);
325 auto file1 = pandasm::AsmEmitter::Emit(res1.Value());
326 auto file2 = pandasm::AsmEmitter::Emit(res2.Value());
327 auto jsPandaFile1 = std::make_shared<JSPandaFile>(file1.release(), CString(filename1), CreateMode::DFX);
328 auto jsPandaFile2 = std::make_shared<JSPandaFile>(file2.release(), CString(filename2), CreateMode::DFX);
329 EXPECT_TRUE(jsPandaFile1 != nullptr);
330 EXPECT_TRUE(jsPandaFile2 != nullptr);
331 auto debugExtractor1 = std::make_unique<DebugInfoExtractor>(jsPandaFile1.get());
332 auto debugExtractor2 = std::make_unique<DebugInfoExtractor>(jsPandaFile2.get());
333 auto methods1 = JSStackTrace::ReadAllMethodInfos(jsPandaFile1);
334 auto methods2 = JSStackTrace::ReadAllMethodInfos(jsPandaFile2);
335
336 uintptr_t byteCodePc1 = methods1[0].codeBegin;
337 uintptr_t byteCodePc2 = methods2[0].codeBegin;
338 uintptr_t mapBase1 = reinterpret_cast<uintptr_t>(jsPandaFile1->GetHeader());
339 uintptr_t mapBase2 = reinterpret_cast<uintptr_t>(jsPandaFile2->GetHeader());
340 uintptr_t loadOffset1 = 0;
341 uintptr_t loadOffset2 = 0;
342 const uint8_t* data1 = jsPandaFile1->GetPandaFile()->GetBase();
343 const uint8_t* data2 = jsPandaFile2->GetPandaFile()->GetBase();
344 uint64_t dataSize1 = jsPandaFile1->GetFileSize();
345 uint64_t dataSize2 = jsPandaFile2->GetFileSize();
346 uintptr_t extractorptr1 = 0;
347 uintptr_t extractorptr2 = 0;
348 JsFunction jsFunction1;
349 JsFunction jsFunction2;
350
351 auto ret = ark_create_js_symbol_extractor(&extractorptr1);
352 EXPECT_TRUE(ret == 1);
353 EXPECT_TRUE(extractorptr1 != 0);
354 ret = ark_create_js_symbol_extractor(&extractorptr2);
355 EXPECT_TRUE(ret == 1);
356 EXPECT_TRUE(extractorptr2 != 0);
357
358 ret = ark_parse_js_frame_info(byteCodePc1, mapBase1, loadOffset1,
359 reinterpret_cast<uint8_t *>(const_cast<char*>(pfdata1)),
360 strlen(pfdata1) + 1, extractorptr1, &jsFunction1);
361 EXPECT_TRUE(ret == -1);
362
363 ret = ark_parse_js_frame_info(byteCodePc1, mapBase1, loadOffset1,
364 const_cast<uint8_t*>(data1), dataSize1, extractorptr1, &jsFunction1);
365 EXPECT_TRUE(ret == 1);
366 EXPECT_TRUE(std::string(jsFunction1.functionName) == "foo");
367
368 ret = ark_parse_js_frame_info(byteCodePc1, mapBase1, loadOffset1,
369 const_cast<uint8_t*>(data1), dataSize1 + 1, 0, &jsFunction1);
370 EXPECT_TRUE(ret == -1);
371
372 ret = ark_parse_js_frame_info(byteCodePc1, mapBase1, loadOffset1,
373 nullptr, 0, extractorptr1, &jsFunction1);
374 EXPECT_TRUE(ret == -1);
375
376 ret = ark_parse_js_frame_info(byteCodePc1, mapBase1, loadOffset1,
377 const_cast<uint8_t*>(data2), dataSize2, extractorptr2, &jsFunction1);
378 EXPECT_TRUE(ret == -1);
379
380 ret = ark_parse_js_frame_info(byteCodePc2, mapBase1, loadOffset1,
381 const_cast<uint8_t*>(data2), dataSize2, extractorptr2, &jsFunction1);
382 EXPECT_TRUE(ret == -1);
383
384 ret = ark_parse_js_frame_info(byteCodePc2, mapBase1, loadOffset1,
385 const_cast<uint8_t*>(data2), dataSize2, extractorptr2, &jsFunction1);
386 EXPECT_TRUE(ret == -1);
387
388 ret = ark_parse_js_frame_info(byteCodePc2, mapBase2, loadOffset2,
389 const_cast<uint8_t*>(data2), dataSize2, extractorptr2, &jsFunction2);
390 EXPECT_TRUE(ret == 1);
391 EXPECT_TRUE(std::string(jsFunction2.functionName) == "func_main_0");
392
393 ret = ark_destory_js_symbol_extractor(extractorptr1);
394 EXPECT_TRUE(ret == 1);
395
396 ret = ark_destory_js_symbol_extractor(extractorptr2);
397 EXPECT_TRUE(ret == 1);
398 }
399
400 /**
401 * @tc.name: BuildJsStackInfo
402 * @tc.desc: Check whether the result returned through "BuildJsStackInfo" function is within expectations;
403 * @tc.type: FUNC
404 * @tc.require:
405 */
HWTEST_F_L0(JsStackInfoTest,TestBuildJsStackInfo)406 HWTEST_F_L0(JsStackInfoTest, TestBuildJsStackInfo)
407 {
408 auto jsFrame = JsStackInfo::BuildJsStackInfo(thread);
409 EXPECT_TRUE(jsFrame.empty());
410 }
411
412 /**
413 * @tc.name: ark_destory_local
414 * @tc.desc: Check whether the result returned through "ark_destory_local" function is within expectations;
415 * @tc.type: FUNC
416 * @tc.require:
417 */
HWTEST_F_L0(JsStackInfoTest,TestArkDestoryLocal)418 HWTEST_F_L0(JsStackInfoTest, TestArkDestoryLocal)
419 {
420 auto ret = ark_destroy_local(); // Direct destruct without creating Pointers
421 EXPECT_TRUE(ret);
422 ret = ark_create_local(); // ref count = 1
423 ret = ark_create_local(); // ref count = 2
424 EXPECT_TRUE(ret);
425 auto trace = JSStackTrace::GetInstance();
426 EXPECT_TRUE(trace != nullptr);
427 ret = ark_destroy_local(); // ref count = 1
428 trace = JSStackTrace::GetInstance();
429 EXPECT_TRUE(trace != nullptr);
430 ret = ark_destroy_local(); // ref count = 0
431 trace = JSStackTrace::GetInstance();
432 EXPECT_TRUE(trace == nullptr);
433 EXPECT_TRUE(ret);
434 ret = ark_destroy_local(); // multiple destory
435 EXPECT_TRUE(ret);
436
437 // Create and destruct multiple times within the process
438 ret = ark_create_local(); // ref count = 1
439 trace = JSStackTrace::GetInstance();
440 EXPECT_TRUE(trace != nullptr);
441 ret = ark_destroy_local();
442 EXPECT_TRUE(ret);
443 }
444
HWTEST_F_L0(JsStackInfoTest,TestStepArk__001)445 HWTEST_F_L0(JsStackInfoTest, TestStepArk__001)
446 {
447 void *ctx = nullptr;
448 uintptr_t sp = 0;
449 uintptr_t pc = 0;
450 bool isJsFrame = true;
451 uintptr_t frame[10][3];
452 uintptr_t fp[10];
453 for (int i = 0; i < 10; i++) {
454 frame[i][0] = 0;
455 frame[i][1] = 0;
456 }
457 fp[0] = reinterpret_cast<uintptr_t>(&frame[0][2]) + 8;
458 for (int i = 1; i < 10; i++) {
459 fp[i] = fp[i-1] + 24;
460 }
461 ArkStepParam arkStepParam{ &fp[0], &sp, &pc, &isJsFrame };
462 frame[0][2] = static_cast<uintptr_t>(FrameType::INTERPRETER_CONSTRUCTOR_FRAME);
463 ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &arkStepParam));
464 frame[1][2] = static_cast<uintptr_t>(FrameType::INTERPRETER_FAST_NEW_FRAME);
465 arkStepParam.fp = &fp[1];
466 ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &arkStepParam));
467 frame[2][2] = static_cast<uintptr_t>(FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME);
468 arkStepParam.fp = &fp[2];
469 ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &arkStepParam));
470 frame[3][2] = static_cast<uintptr_t>(FrameType::ASM_INTERPRETER_ENTRY_FRAME);
471 arkStepParam.fp = &fp[3];
472 ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &arkStepParam));
473 frame[4][2] = static_cast<uintptr_t>(FrameType::BUILTIN_ENTRY_FRAME);
474 arkStepParam.fp = &fp[4];
475 ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &arkStepParam));
476 frame[5][2] = static_cast<uintptr_t>(FrameType::BUILTIN_FRAME_WITH_ARGV_STACK_OVER_FLOW_FRAME);
477 arkStepParam.fp = &fp[5];
478 ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &arkStepParam));
479 frame[6][2] = static_cast<uintptr_t>(FrameType::BASELINE_BUILTIN_FRAME);
480 arkStepParam.fp = &fp[6];
481 ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &arkStepParam));
482 frame[7][2] = static_cast<uintptr_t>(FrameType::ASM_BRIDGE_FRAME);
483 arkStepParam.fp = &fp[7];
484 ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &arkStepParam));
485 frame[8][2] = static_cast<uintptr_t>(FrameType::LEAVE_FRAME);
486 arkStepParam.fp = &fp[8];
487 ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &arkStepParam));
488 frame[9][2] = static_cast<uintptr_t>(FrameType::LEAVE_FRAME_WITH_ARGV);
489 arkStepParam.fp = &fp[9];
490 ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &arkStepParam));
491 }
492
HWTEST_F_L0(JsStackInfoTest,TestStepArk__002)493 HWTEST_F_L0(JsStackInfoTest, TestStepArk__002)
494 {
495 void *ctx = nullptr;
496 uintptr_t sp = 0;
497 uintptr_t pc = 0;
498 bool isJsFrame = true;
499 uintptr_t frame[30][3];
500 uintptr_t fp[30];
501 for (int i = 0; i < 30; i++) {
502 frame[i][0] = 0;
503 frame[i][1] = 0;
504 }
505 fp[0] = reinterpret_cast<uintptr_t>(&frame[0][2]) + 8;
506 for (int i = 1; i < 30; i++) {
507 fp[i] = fp[i-1] + 24;
508 }
509 ArkStepParam arkStepParam{ &fp[0], &sp, &pc, &isJsFrame };
510 frame[0][2] = static_cast<uintptr_t>(FrameType::BUILTIN_CALL_LEAVE_FRAME);
511 ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &arkStepParam));
512 frame[1][2] = static_cast<uintptr_t>(FrameType::OPTIMIZED_FRAME);
513 arkStepParam.fp = &fp[1];
514 ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &arkStepParam));
515 frame[2][2] = static_cast<uintptr_t>(FrameType::ASM_INTERPRETER_BRIDGE_FRAME);
516 arkStepParam.fp = &fp[2];
517 ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &arkStepParam));
518 frame[3][2] = static_cast<uintptr_t>(FrameType::OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME);
519 arkStepParam.fp = &fp[3];
520 ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &arkStepParam));
521 frame[4][2] = static_cast<uintptr_t>(FrameType::INTERPRETER_CONSTRUCTOR_FRAME);
522 arkStepParam.fp = &fp[4];
523 ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &arkStepParam));
524 frame[5][2] = static_cast<uintptr_t>(FrameType::OPTIMIZED_ENTRY_FRAME);
525 arkStepParam.fp = &fp[5];
526 ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &arkStepParam));
527 frame[6][2] = static_cast<uintptr_t>(FrameType::ASM_BRIDGE_FRAME);
528 arkStepParam.fp = &fp[6];
529 ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &arkStepParam));
530 frame[7][2] = static_cast<uintptr_t>(FrameType::OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME);
531 arkStepParam.fp = &fp[7];
532 ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &arkStepParam));
533 frame[8][2] = static_cast<uintptr_t>(FrameType::OPTIMIZED_JS_FUNCTION_FRAME);
534 arkStepParam.fp = &fp[8];
535 ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &arkStepParam));
536 frame[9][2] = 100;
537 arkStepParam.fp = &fp[9];
538 ASSERT_TRUE(step_ark(ctx, ReadMemFunc, &arkStepParam));
539 }
540
HWTEST_F_L0(JsStackInfoTest,TestLocalParseJsFrameInfo__001)541 HWTEST_F_L0(JsStackInfoTest, TestLocalParseJsFrameInfo__001)
542 {
543 const char *filename = "__JsStackInfoTest1.pa";
544 const char *pfdata = R"(
545 .function void foo() {
546 return
547 }
548 )";
549
550 auto pfManager = JSPandaFileManager::GetInstance();
551
552 pandasm::Parser parser1;
553 auto res = parser1.Parse(pfdata);
554 auto file = pandasm::AsmEmitter::Emit(res.Value());
555 auto jsPandaFile = pfManager->NewJSPandaFile(file.release(), CString(filename));
556 pfManager->AddJSPandaFile(jsPandaFile);
557 EXPECT_TRUE(jsPandaFile != nullptr);
558 auto methods = JSStackTrace::ReadAllMethodInfos(jsPandaFile);
559
560 uintptr_t byteCodePc = methods[0].codeBegin;
561 uintptr_t mapBase = reinterpret_cast<uintptr_t>(jsPandaFile->GetHeader());
562 uintptr_t loadOffset = 0;
563 JsFunction jsFunction;
564
565 // Incorrect invocation demonstration
566 auto ret = ark_parse_js_frame_info_local(byteCodePc, mapBase, loadOffset, &jsFunction);
567 EXPECT_TRUE(ret == -1);
568
569 // Correct invocation demonstration
570 ark_create_local();
571 ret = ark_parse_js_frame_info_local(byteCodePc, mapBase, loadOffset, &jsFunction);
572 EXPECT_TRUE(ret == 1);
573
574 ret = ark_parse_js_frame_info_local(byteCodePc, mapBase, loadOffset, &jsFunction);
575 EXPECT_TRUE(ret == 1);
576
577 ark_destroy_local();
578
579 pfManager->RemoveJSPandaFile(jsPandaFile.get());
580 }
581
HWTEST_F_L0(JsStackInfoTest,TestLocalParseJsFrameInfo__002)582 HWTEST_F_L0(JsStackInfoTest, TestLocalParseJsFrameInfo__002)
583 {
584 const char *filename = "__JsStackInfoTest1.pa";
585 const char *pfdata = R"(
586 .function void foo() {
587 return
588 }
589 )";
590
591 auto pfManager = JSPandaFileManager::GetInstance();
592
593 pandasm::Parser parser1;
594 auto res = parser1.Parse(pfdata);
595 auto file = pandasm::AsmEmitter::Emit(res.Value());
596 auto jsPandaFile = pfManager->NewJSPandaFile(file.release(), CString(filename));
597 EXPECT_TRUE(jsPandaFile != nullptr);
598 auto methods = JSStackTrace::ReadAllMethodInfos(jsPandaFile);
599
600 uintptr_t byteCodePc = methods[0].codeBegin;
601 uintptr_t mapBase = reinterpret_cast<uintptr_t>(jsPandaFile->GetHeader());
602 uintptr_t loadOffset = 0;
603 JsFunction jsFunction;
604
605 ark_create_local();
606 auto ret = ark_parse_js_frame_info_local(byteCodePc, mapBase, loadOffset, &jsFunction);
607 ark_destroy_local();
608 // pandafile manager can't find jsPandaFile
609 EXPECT_TRUE(ret == -1);
610 }
611 } // namespace panda::test