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