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