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 "include/tooling/debug_interface.h"
17 #include "include/tooling/vreg_value.h"
18 #include "intrinsics.h"
19 #include "libpandabase/utils/logger.h"
20 #include "plugins/ets/runtime/ets_exceptions.h"
21 #include "plugins/ets/runtime/tooling/helpers.h"
22 #include "plugins/ets/runtime/types/ets_primitives.h"
23
24 namespace ark::ets::intrinsics {
25
SetNotFoundException(EtsLong regNumber,EtsCoroutine * coroutine,std::string_view typeName)26 static void SetNotFoundException(EtsLong regNumber, EtsCoroutine *coroutine, std::string_view typeName)
27 {
28 auto errorMsg =
29 "No local variable found at vreg #" + std::to_string(regNumber) + " and type " + std::string(typeName);
30 ark::ets::ThrowEtsException(
31 coroutine,
32 utf::Mutf8AsCString(
33 Runtime::GetCurrent()->GetLanguageContext(panda_file::SourceLang::ETS).GetNoSuchFieldErrorDescriptor()),
34 errorMsg);
35 }
36
SetRuntimeException(EtsLong regNumber,EtsCoroutine * coroutine,std::string_view typeName)37 static void SetRuntimeException(EtsLong regNumber, EtsCoroutine *coroutine, std::string_view typeName)
38 {
39 auto errorMsg =
40 "Failed to access variable at vreg #" + std::to_string(regNumber) + " and type " + std::string(typeName);
41 ark::ets::ThrowEtsException(coroutine, panda_file_items::class_descriptors::ERROR, errorMsg);
42 }
43
44 template <typename T>
DebuggerAPIGetLocal(EtsCoroutine * coroutine,EtsLong regNumber)45 static T DebuggerAPIGetLocal(EtsCoroutine *coroutine, EtsLong regNumber)
46 {
47 static constexpr uint32_t PREVIOUS_FRAME_DEPTH = 1;
48
49 ASSERT(coroutine);
50
51 if (regNumber < 0) {
52 SetNotFoundException(regNumber, coroutine, ark::ets::tooling::EtsTypeName<T>::NAME);
53 }
54
55 ark::tooling::VRegValue vregValue;
56 auto &debugger = Runtime::GetCurrent()->StartDebugSession()->GetDebugger();
57 auto err = debugger.GetVariable(ark::ets::tooling::CoroutineToPtThread(coroutine), PREVIOUS_FRAME_DEPTH, regNumber,
58 &vregValue);
59 if (err) {
60 LOG(ERROR, DEBUGGER) << "Failed to get local variable: " << err.value().GetMessage();
61 SetRuntimeException(regNumber, coroutine, ark::ets::tooling::EtsTypeName<T>::NAME);
62 return static_cast<T>(0);
63 }
64 return ark::ets::tooling::VRegValueToEtsValue<T>(vregValue);
65 }
66
DebuggerAPIGetLocalBoolean(EtsLong regNumber)67 EtsBoolean DebuggerAPIGetLocalBoolean(EtsLong regNumber)
68 {
69 auto *coroutine = EtsCoroutine::GetCurrent();
70 return DebuggerAPIGetLocal<EtsBoolean>(coroutine, regNumber);
71 }
72
DebuggerAPIGetLocalByte(EtsLong regNumber)73 EtsByte DebuggerAPIGetLocalByte(EtsLong regNumber)
74 {
75 auto *coroutine = EtsCoroutine::GetCurrent();
76 return DebuggerAPIGetLocal<EtsByte>(coroutine, regNumber);
77 }
78
DebuggerAPIGetLocalShort(EtsLong regNumber)79 EtsShort DebuggerAPIGetLocalShort(EtsLong regNumber)
80 {
81 auto *coroutine = EtsCoroutine::GetCurrent();
82 return DebuggerAPIGetLocal<EtsShort>(coroutine, regNumber);
83 }
84
DebuggerAPIGetLocalChar(EtsLong regNumber)85 EtsChar DebuggerAPIGetLocalChar(EtsLong regNumber)
86 {
87 auto *coroutine = EtsCoroutine::GetCurrent();
88 return DebuggerAPIGetLocal<EtsChar>(coroutine, regNumber);
89 }
90
DebuggerAPIGetLocalInt(EtsLong regNumber)91 EtsInt DebuggerAPIGetLocalInt(EtsLong regNumber)
92 {
93 auto *coroutine = EtsCoroutine::GetCurrent();
94 return DebuggerAPIGetLocal<EtsInt>(coroutine, regNumber);
95 }
96
DebuggerAPIGetLocalFloat(EtsLong regNumber)97 EtsFloat DebuggerAPIGetLocalFloat(EtsLong regNumber)
98 {
99 auto *coroutine = EtsCoroutine::GetCurrent();
100 return DebuggerAPIGetLocal<EtsFloat>(coroutine, regNumber);
101 }
102
DebuggerAPIGetLocalDouble(EtsLong regNumber)103 EtsDouble DebuggerAPIGetLocalDouble(EtsLong regNumber)
104 {
105 auto *coroutine = EtsCoroutine::GetCurrent();
106 return DebuggerAPIGetLocal<EtsDouble>(coroutine, regNumber);
107 }
108
DebuggerAPIGetLocalLong(EtsLong regNumber)109 EtsLong DebuggerAPIGetLocalLong(EtsLong regNumber)
110 {
111 auto *coroutine = EtsCoroutine::GetCurrent();
112 return DebuggerAPIGetLocal<EtsLong>(coroutine, regNumber);
113 }
114
DebuggerAPIGetLocalObject(EtsLong regNumber)115 EtsObject *DebuggerAPIGetLocalObject(EtsLong regNumber)
116 {
117 auto *coroutine = EtsCoroutine::GetCurrent();
118 [[maybe_unused]] HandleScope<ObjectHeader *> scope(coroutine);
119
120 auto *obj = DebuggerAPIGetLocal<ObjectHeader *>(coroutine, regNumber);
121 obj = (obj == nullptr) ? coroutine->GetUndefinedObject() : obj;
122 VMHandle<ObjectHeader> objHandle(coroutine, obj);
123 return EtsObject::FromCoreType(objHandle.GetPtr());
124 }
125
126 template <typename T>
DebuggerAPISetLocal(EtsCoroutine * coroutine,EtsLong regNumber,T value)127 static void DebuggerAPISetLocal(EtsCoroutine *coroutine, EtsLong regNumber, T value)
128 {
129 static constexpr uint32_t PREVIOUS_FRAME_DEPTH = 1;
130
131 ASSERT(coroutine);
132
133 if (regNumber < 0) {
134 SetNotFoundException(regNumber, coroutine, ark::ets::tooling::EtsTypeName<T>::NAME);
135 return;
136 }
137
138 auto vregValue = ark::ets::tooling::EtsValueToVRegValue<T>(value);
139 auto &debugger = Runtime::GetCurrent()->StartDebugSession()->GetDebugger();
140 auto err = debugger.SetVariable(ark::ets::tooling::CoroutineToPtThread(coroutine), PREVIOUS_FRAME_DEPTH, regNumber,
141 vregValue);
142 if (err) {
143 LOG(ERROR, DEBUGGER) << "Failed to set local variable: " << err.value().GetMessage();
144 SetRuntimeException(regNumber, coroutine, ark::ets::tooling::EtsTypeName<T>::NAME);
145 }
146 }
147
DebuggerAPISetLocalBoolean(EtsLong regNumber,EtsBoolean value)148 void DebuggerAPISetLocalBoolean(EtsLong regNumber, EtsBoolean value)
149 {
150 auto coroutine = EtsCoroutine::GetCurrent();
151 DebuggerAPISetLocal<EtsBoolean>(coroutine, regNumber, value);
152 }
153
DebuggerAPISetLocalByte(EtsLong regNumber,EtsByte value)154 void DebuggerAPISetLocalByte(EtsLong regNumber, EtsByte value)
155 {
156 auto coroutine = EtsCoroutine::GetCurrent();
157 DebuggerAPISetLocal<EtsByte>(coroutine, regNumber, value);
158 }
159
DebuggerAPISetLocalShort(EtsLong regNumber,EtsShort value)160 void DebuggerAPISetLocalShort(EtsLong regNumber, EtsShort value)
161 {
162 auto coroutine = EtsCoroutine::GetCurrent();
163 DebuggerAPISetLocal<EtsShort>(coroutine, regNumber, value);
164 }
165
DebuggerAPISetLocalChar(EtsLong regNumber,EtsChar value)166 void DebuggerAPISetLocalChar(EtsLong regNumber, EtsChar value)
167 {
168 auto coroutine = EtsCoroutine::GetCurrent();
169 DebuggerAPISetLocal<EtsChar>(coroutine, regNumber, value);
170 }
171
DebuggerAPISetLocalInt(EtsLong regNumber,EtsInt value)172 void DebuggerAPISetLocalInt(EtsLong regNumber, EtsInt value)
173 {
174 auto coroutine = EtsCoroutine::GetCurrent();
175 DebuggerAPISetLocal<EtsInt>(coroutine, regNumber, value);
176 }
177
DebuggerAPISetLocalFloat(EtsLong regNumber,EtsFloat value)178 void DebuggerAPISetLocalFloat(EtsLong regNumber, EtsFloat value)
179 {
180 auto coroutine = EtsCoroutine::GetCurrent();
181 DebuggerAPISetLocal<EtsFloat>(coroutine, regNumber, value);
182 }
183
DebuggerAPISetLocalDouble(EtsLong regNumber,EtsDouble value)184 void DebuggerAPISetLocalDouble(EtsLong regNumber, EtsDouble value)
185 {
186 auto coroutine = EtsCoroutine::GetCurrent();
187 DebuggerAPISetLocal<EtsDouble>(coroutine, regNumber, value);
188 }
189
DebuggerAPISetLocalLong(EtsLong regNumber,EtsLong value)190 void DebuggerAPISetLocalLong(EtsLong regNumber, EtsLong value)
191 {
192 auto coroutine = EtsCoroutine::GetCurrent();
193 DebuggerAPISetLocal<EtsLong>(coroutine, regNumber, value);
194 }
195
DebuggerAPISetLocalObject(EtsLong regNumber,EtsObject * value)196 void DebuggerAPISetLocalObject(EtsLong regNumber, EtsObject *value)
197 {
198 auto coroutine = EtsCoroutine::GetCurrent();
199 [[maybe_unused]] HandleScope<ObjectHeader *> scope(coroutine);
200 VMHandle<EtsObject> objHandle(coroutine, value->GetCoreType());
201
202 DebuggerAPISetLocal<ObjectHeader *>(coroutine, regNumber, objHandle.GetPtr()->GetCoreType());
203 }
204
205 } // namespace ark::ets::intrinsics
206