• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "ecmascript/dfx/stackinfo/js_stackinfo.h"
19 #include "ecmascript/tests/test_helper.h"
20 
21 using namespace panda::ecmascript;
22 
23 namespace panda::test {
24 class JsStackInfoTest : public testing::Test {
25 public:
SetUpTestCase()26     static void SetUpTestCase()
27     {
28         GTEST_LOG_(INFO) << "SetUpTestCase";
29     }
30 
TearDownTestCase()31     static void TearDownTestCase()
32     {
33         GTEST_LOG_(INFO) << "TearDownCase";
34     }
35 
SetUp()36     void SetUp() override
37     {
38         TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
39         instance->SetEnableForceGC(false);
40     }
41 
TearDown()42     void TearDown() override
43     {
44         TestHelper::DestroyEcmaVMWithScope(instance, scope);
45     }
46 
47     EcmaVM *instance {nullptr};
48     EcmaHandleScope *scope {nullptr};
49     JSThread *thread {nullptr};
50 };
51 
HWTEST_F_L0(JsStackInfoTest,FrameCheckTest)52 HWTEST_F_L0(JsStackInfoTest, FrameCheckTest)
53 {
54     uintptr_t frame[22];
55     frame[0] = reinterpret_cast<uintptr_t>(FrameType::OPTIMIZED_FRAME);
56     frame[1] = reinterpret_cast<uintptr_t>(FrameType::OPTIMIZED_ENTRY_FRAME);
57     frame[2] = reinterpret_cast<uintptr_t>(FrameType::OPTIMIZED_JS_FUNCTION_FRAME);
58     frame[3] = reinterpret_cast<uintptr_t>(FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME);
59     frame[4] = reinterpret_cast<uintptr_t>(FrameType::ASM_BRIDGE_FRAME);
60     frame[5] = reinterpret_cast<uintptr_t>(FrameType::LEAVE_FRAME);
61     frame[6] = reinterpret_cast<uintptr_t>(FrameType::LEAVE_FRAME_WITH_ARGV);
62     frame[7] = reinterpret_cast<uintptr_t>(FrameType::BUILTIN_CALL_LEAVE_FRAME);
63     frame[8] = reinterpret_cast<uintptr_t>(FrameType::INTERPRETER_FRAME);
64     frame[9] = reinterpret_cast<uintptr_t>(FrameType::ASM_INTERPRETER_FRAME);
65     frame[10] = reinterpret_cast<uintptr_t>(FrameType::INTERPRETER_CONSTRUCTOR_FRAME);
66     frame[11] = reinterpret_cast<uintptr_t>(FrameType::BUILTIN_FRAME);
67     frame[12] = reinterpret_cast<uintptr_t>(FrameType::BUILTIN_FRAME_WITH_ARGV);
68     frame[13] = reinterpret_cast<uintptr_t>(FrameType::BUILTIN_ENTRY_FRAME);
69     frame[14] = reinterpret_cast<uintptr_t>(FrameType::INTERPRETER_BUILTIN_FRAME);
70     frame[15] = reinterpret_cast<uintptr_t>(FrameType::INTERPRETER_FAST_NEW_FRAME);
71     frame[16] = reinterpret_cast<uintptr_t>(FrameType::INTERPRETER_ENTRY_FRAME);
72     frame[17] = reinterpret_cast<uintptr_t>(FrameType::ASM_INTERPRETER_ENTRY_FRAME);
73     frame[18] = reinterpret_cast<uintptr_t>(FrameType::ASM_INTERPRETER_BRIDGE_FRAME);
74     frame[19] = reinterpret_cast<uintptr_t>(FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME);
75     frame[20] = reinterpret_cast<uintptr_t>(FrameType::OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME);
76     frame[21] = reinterpret_cast<uintptr_t>(FrameType::BUILTIN_FRAME_WITH_ARGV_STACK_OVER_FLOW_FRAME);
77 
78     for (int i = 0; i < 22; i++) {
79         bool ret1 = ArkFrameCheck(frame[i]);
80         if (i == 1 || i == 17) {
81             EXPECT_TRUE(ret1 == true);
82         } else {
83             EXPECT_TRUE(ret1 == false);
84         }
85         bool ret2 = IsFunctionFrame(frame[i]);
86         if (i == 2 || i == 3 || i == 8 || i == 9 || i == 10 || i == 15) {
87             EXPECT_TRUE(ret2 == true);
88         } else {
89             EXPECT_TRUE(ret2 == false);
90         }
91     }
92 }
93 
HWTEST_F_L0(JsStackInfoTest,TranslateByteCodePc)94 HWTEST_F_L0(JsStackInfoTest, TranslateByteCodePc)
95 {
96     std::vector<MethodInfo> vec = {
97         {0, 0, 24},
98         {1, 24, 30},
99         {2, 54, 56},
100         {3, 120, 60}
101     };
102     uintptr_t realPc = 115;
103 
104     auto ret = TranslateByteCodePc(realPc, vec);
105     EXPECT_TRUE(ret != std::nullopt);
106 
107     vec.clear();
108     ret = TranslateByteCodePc(realPc, vec);
109     EXPECT_TRUE(ret == std::nullopt);
110 
111     vec.push_back({2, 54, 56});
112     ret = TranslateByteCodePc(realPc, vec);
113     EXPECT_TRUE(ret != std::nullopt);
114 }
115 
HWTEST_F_L0(JsStackInfoTest,GetArkNativeFrameInfo)116 HWTEST_F_L0(JsStackInfoTest, GetArkNativeFrameInfo)
117 {
118     if (sizeof(uintptr_t) == sizeof(uint32_t)) {  // 32 bit
119         // The frame structure is different between 32 bit and 64 bit.
120         // Skip 32 bit because there is no ArkJS Heap.
121         return;
122     }
123 
124     uintptr_t pc = 0;
125     uintptr_t fp = 0;
126     uintptr_t sp = 0;
127     size_t size = 22;
128     JsFrame jsFrame[22];
129     bool ret = GetArkNativeFrameInfo(getpid(), &pc, &fp, &sp, &jsFrame, &size);
130     EXPECT_FALSE(ret);
131     EXPECT_TRUE(size == 22);
132 
133     pc = 1234;
134     fp = 62480;
135     sp = 62496;
136     bool ret = GetArkNativeFrameInfo(getpid(), &pc, &fp, &sp, &jsFrame, &size);
137     EXPECT_FALSE(ret);
138     EXPECT_TRUE(size == 22);
139 
140     JSTaggedType frame1[3];  // 3: size of ASM_INTERPRETER_ENTRY_FRAME
141     frame1[0] = pc;  // 0: pc
142     frame1[1] = 62480;  // 1: base.prev
143     frame1[2] = static_cast<JSTaggedType>(FrameType::ASM_INTERPRETER_ENTRY_FRAME);  // 2: base.type
144     uintptr_t fp_frame1 = reinterpret_cast<uintptr_t>(&frame3[3]);  // 3: bottom of frame
145 
146     JSTaggedType frame2[9];  // 9: size of AsmInterpretedFrame
147     frame2[0] = JSTaggedValue::Hole().GetRawData();  // 0: function
148     frame2[1] = JSTaggedValue::Hole().GetRawData();  // 1: thisObj
149     frame2[2] = JSTaggedValue::Hole().GetRawData();  // 2: acc
150     frame2[3] = JSTaggedValue::Hole().GetRawData();  // 3: env
151     frame2[4] = static_cast<JSTaggedType>(0);  // 4: callSize
152     frame2[5] = static_cast<JSTaggedType>(0);  // 5: fp
153     frame2[6] = reinterpret_cast<JSTaggedType>(&bytecode[2]);  // 6: pc
154     frame2[7] = fp_frame1;  // 7: base.prev
155     frame2[8] = static_cast<JSTaggedType>(FrameType::ASM_INTERPRETER_FRAME);  // 8: base.type
156     uintptr_t fp_frame2 = reinterpret_cast<uintptr_t>(&frame[9]);  // 9: bottom of frame
157 
158     JSTaggedType frame3[6];  // 6: size of BUILTIN_FRAME
159     frame3[0] = JSTaggedValue::Hole().GetRawData();  // 0: stackArgs
160     frame3[1] = JSTaggedValue::Hole().GetRawData();  // 1:numArgs
161     frame3[2] = JSTaggedValue::Hole().GetRawData();  // 2: thread
162     frame3[3] = JSTaggedValue::Hole().GetRawData();  // 3: returnAddr
163     frame3[4] = fp_frame2;  // 4: prevFp
164     frame3[5] = static_cast<JSTaggedType>(FrameType::BUILTIN_FRAME);  // 5: type
165     uintptr_t fp_frame3 = reinterpret_cast<uintptr_t>(&frame1[6]);  // 6: bottom of frame
166     fp = fp_frame3;
167     bool ret = GetArkNativeFrameInfo(getpid(), &pc, &fp, &sp, &jsFrame, &size);
168     EXPECT_TRUE(ret);
169     EXPECT_TRUE(sp = &fp_frame1);
170     EXPECT_TRUE(pc = 1234);
171     EXPECT_TRUE(fp = 62480);
172 }
173 
HWTEST_F_L0(JsStackInfoTest,BuildJsStackInfo)174 HWTEST_F_L0(JsStackInfoTest, BuildJsStackInfo)
175 {
176     auto jsFrame = JsStackInfo::BuildJsStackInfo(thread);
177     EXPECT_TRUE(jsFrame.empty());
178 }
179 }  // namespace panda::test
180