• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2022 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 <gtest/gtest.h>
17 
18 #include <vector>
19 
20 #include "runtime/entrypoints/entrypoints.h"
21 #include "runtime/include/method.h"
22 #include "runtime/tooling/debugger.h"
23 #include "runtime/tests/test_utils.h"
24 
25 #include "assembly-emitter.h"
26 #include "assembly-parser.h"
27 
28 namespace panda::debugger::test {
29 
30 class DebuggerTest : public testing::Test {
31 public:
DebuggerTest()32     DebuggerTest()
33     {
34         RuntimeOptions options;
35         options.SetShouldLoadBootPandaFiles(false);
36         options.SetShouldInitializeIntrinsics(false);
37         // this test doesn't check GC logic - just to make test easier without any handles
38         options.SetGcType("epsilon");
39         Runtime::Create(options);
40         thread_ = panda::MTManagedThread::GetCurrent();
41         thread_->ManagedCodeBegin();
42     }
43 
~DebuggerTest()44     ~DebuggerTest()
45     {
46         thread_->ManagedCodeEnd();
47         Runtime::Destroy();
48     }
49 
50 protected:
51     panda::MTManagedThread *thread_;
52 };
53 
ToPtr(uint64_t v)54 static ObjectHeader *ToPtr(uint64_t v)
55 {
56     return reinterpret_cast<ObjectHeader *>(static_cast<object_pointer_type>(v));
57 }
58 
FromPtr(ObjectHeader * ptr)59 static uint64_t FromPtr(ObjectHeader *ptr)
60 {
61     return static_cast<object_pointer_type>(reinterpret_cast<uint64_t>(ptr));
62 }
63 
64 template <bool is_dynamic = false>
CreateFrame(size_t nregs,Method * method,Frame * prev)65 static Frame *CreateFrame(size_t nregs, Method *method, Frame *prev)
66 {
67     uint32_t ext_sz = EmptyExtFrameDataSize;
68     void *mem = aligned_alloc(8, Frame::GetAllocSize(Frame::GetActualSize<is_dynamic>(nregs), ext_sz));
69     return new (Frame::FromExt(mem, ext_sz)) Frame(mem, method, prev, nregs);
70 }
71 
FreeFrame(Frame * frame)72 static void FreeFrame(Frame *frame)
73 {
74     std::free(frame->GetExt());
75 }
76 
TEST_F(DebuggerTest,Frame)77 TEST_F(DebuggerTest, Frame)
78 {
79     pandasm::Parser p;
80 
81     auto source = R"(
82         .function void foo(i32 a0, i32 a1) {
83             movi v0, 1
84             movi v1, 2
85             return.void
86         }
87     )";
88 
89     std::string src_filename = "src.pa";
90     auto res = p.Parse(source, src_filename);
91     ASSERT(p.ShowError().err == pandasm::Error::ErrorType::ERR_NONE);
92 
93     auto file_ptr = pandasm::AsmEmitter::Emit(res.Value());
94     ASSERT(file_ptr != nullptr);
95 
96     PandaString descriptor;
97     auto class_id = file_ptr->GetClassId(ClassHelper::GetDescriptor(utf::CStringAsMutf8("_GLOBAL"), &descriptor));
98     ASSERT_TRUE(class_id.IsValid());
99 
100     panda_file::ClassDataAccessor cda(*file_ptr, class_id);
101     panda_file::File::EntityId method_id;
102     panda_file::File::EntityId code_id;
103 
104     cda.EnumerateMethods([&](panda_file::MethodDataAccessor &mda) {
105         method_id = mda.GetMethodId();
106         ASSERT_TRUE(mda.GetCodeId());
107         code_id = mda.GetCodeId().value();
108     });
109 
110     panda_file::CodeDataAccessor code_data_accessor(*file_ptr, code_id);
111     auto nargs = code_data_accessor.GetNumArgs();
112     auto nregs = code_data_accessor.GetNumVregs();
113 
114     constexpr size_t BYTECODE_OFFSET = 0xeeff;
115 
116     Method method(nullptr, file_ptr.get(), method_id, code_id, 0, nargs, nullptr);
117     panda::Frame *frame = test::CreateFrame(nregs + nargs, &method, nullptr);
118     frame->SetBytecodeOffset(BYTECODE_OFFSET);
119 
120     struct VRegValue {
121         uint64_t value {};
122         bool is_ref {};
123     };
124 
125     std::vector<VRegValue> regs {{0x1111111122222222, false},
126                                  {FromPtr(panda::mem::AllocateNullifiedPayloadString(1)), true},
127                                  {0x3333333344444444, false},
128                                  {FromPtr(panda::mem::AllocateNullifiedPayloadString(1)), true}};
129 
130     auto frame_handler = StaticFrameHandler(frame);
131     for (size_t i = 0; i < regs.size(); i++) {
132         if (regs[i].is_ref) {
133             frame_handler.GetVReg(i).SetReference(ToPtr(regs[i].value));
134         } else {
135             frame_handler.GetVReg(i).SetPrimitive(static_cast<int64_t>(regs[i].value));
136         }
137     }
138 
139     {
140         VRegValue acc {0xaaaaaaaabbbbbbbb, false};
141         frame->GetAccAsVReg().SetPrimitive(static_cast<int64_t>(acc.value));
142         tooling::PtDebugFrame debug_frame(frame->GetMethod(), frame);
143 
144         EXPECT_EQ(debug_frame.GetVRegNum(), nregs);
145         EXPECT_EQ(debug_frame.GetArgumentNum(), nargs);
146         EXPECT_EQ(debug_frame.GetMethodId(), method_id);
147         EXPECT_EQ(debug_frame.GetBytecodeOffset(), BYTECODE_OFFSET);
148         EXPECT_EQ(debug_frame.GetAccumulator(), acc.value);
149 
150         for (size_t i = 0; i < debug_frame.GetVRegNum(); i++) {
151             EXPECT_EQ(debug_frame.GetVReg(i), regs[i].value);
152         }
153 
154         for (size_t i = 0; i < debug_frame.GetArgumentNum(); i++) {
155             EXPECT_EQ(debug_frame.GetArgument(i), regs[i + nregs].value);
156         }
157     }
158 
159     {
160         VRegValue acc {FromPtr(panda::mem::AllocateNullifiedPayloadString(1)), true};
161         frame->GetAccAsVReg().SetReference(ToPtr(acc.value));
162         tooling::PtDebugFrame debug_frame(frame->GetMethod(), frame);
163 
164         EXPECT_EQ(debug_frame.GetVRegNum(), nregs);
165         EXPECT_EQ(debug_frame.GetArgumentNum(), nargs);
166         EXPECT_EQ(debug_frame.GetMethodId(), method_id);
167         EXPECT_EQ(debug_frame.GetBytecodeOffset(), BYTECODE_OFFSET);
168         EXPECT_EQ(debug_frame.GetAccumulator(), acc.value);
169 
170         for (size_t i = 0; i < debug_frame.GetVRegNum(); i++) {
171             EXPECT_EQ(debug_frame.GetVReg(i), regs[i].value);
172         }
173 
174         for (size_t i = 0; i < debug_frame.GetArgumentNum(); i++) {
175             EXPECT_EQ(debug_frame.GetArgument(i), regs[i + nregs].value);
176         }
177     }
178 
179     test::FreeFrame(frame);
180 }
181 
182 }  // namespace panda::debugger::test
183