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 "runtime/include/exceptions.h"
17
18 #include <libpandabase/utils/cframe_layout.h>
19
20 #include "runtime/bridge/bridge.h"
21 #include "runtime/entrypoints/entrypoints.h"
22 #include "runtime/include/coretypes/string.h"
23 #include "runtime/include/object_header-inl.h"
24 #include "runtime/include/runtime.h"
25 #include "runtime/include/stack_walker.h"
26 #include "runtime/mem/vm_handle.h"
27 #include "libpandabase/utils/asan_interface.h"
28 #include "libpandabase/utils/logger.h"
29 #include "libpandabase/utils/utf.h"
30 #include "libpandafile/class_data_accessor-inl.h"
31 #include "libpandafile/method_data_accessor-inl.h"
32 #include "events/events.h"
33 #include "runtime/handle_base-inl.h"
34
35 namespace panda {
36
ThrowException(LanguageContext ctx,ManagedThread * thread,const uint8_t * mutf8_name,const uint8_t * mutf8_msg)37 void ThrowException(LanguageContext ctx, ManagedThread *thread, const uint8_t *mutf8_name, const uint8_t *mutf8_msg)
38 {
39 ctx.ThrowException(thread, mutf8_name, mutf8_msg);
40 }
41
GetLanguageContext(ManagedThread * thread)42 static LanguageContext GetLanguageContext(ManagedThread *thread)
43 {
44 ASSERT(thread != nullptr);
45
46 StackWalker stack(thread);
47 ASSERT(stack.HasFrame());
48
49 auto *method = stack.GetMethod();
50 ASSERT(method != nullptr);
51
52 return Runtime::GetCurrent()->GetLanguageContext(*method);
53 }
54
ThrowNullPointerException()55 void ThrowNullPointerException()
56 {
57 auto *thread = ManagedThread::GetCurrent();
58 auto ctx = GetLanguageContext(thread);
59 ThrowNullPointerException(ctx, thread);
60 }
61
ThrowNullPointerException(LanguageContext ctx,ManagedThread * thread)62 void ThrowNullPointerException(LanguageContext ctx, ManagedThread *thread)
63 {
64 ThrowException(ctx, thread, ctx.GetNullPointerExceptionClassDescriptor(), nullptr);
65 }
66
ThrowArrayIndexOutOfBoundsException(coretypes::array_ssize_t idx,coretypes::array_size_t length)67 void ThrowArrayIndexOutOfBoundsException(coretypes::array_ssize_t idx, coretypes::array_size_t length)
68 {
69 auto *thread = ManagedThread::GetCurrent();
70 auto ctx = GetLanguageContext(thread);
71 ThrowArrayIndexOutOfBoundsException(idx, length, ctx, thread);
72 }
73
ThrowArrayIndexOutOfBoundsException(coretypes::array_ssize_t idx,coretypes::array_size_t length,LanguageContext ctx,ManagedThread * thread)74 void ThrowArrayIndexOutOfBoundsException(coretypes::array_ssize_t idx, coretypes::array_size_t length,
75 LanguageContext ctx, ManagedThread *thread)
76 {
77 PandaString msg;
78 msg = "idx = " + ToPandaString(idx) + "; length = " + ToPandaString(length);
79
80 ThrowException(ctx, thread, ctx.GetArrayIndexOutOfBoundsExceptionClassDescriptor(),
81 utf::CStringAsMutf8(msg.c_str()));
82 }
83
ThrowIndexOutOfBoundsException(coretypes::array_ssize_t idx,coretypes::array_ssize_t length)84 void ThrowIndexOutOfBoundsException(coretypes::array_ssize_t idx, coretypes::array_ssize_t length)
85 {
86 auto *thread = ManagedThread::GetCurrent();
87 auto ctx = GetLanguageContext(thread);
88
89 PandaString msg;
90 msg = "idx = " + ToPandaString(idx) + "; length = " + ToPandaString(length);
91
92 ThrowException(ctx, thread, ctx.GetIndexOutOfBoundsExceptionClassDescriptor(), utf::CStringAsMutf8(msg.c_str()));
93 }
94
ThrowIllegalStateException(const PandaString & msg)95 void ThrowIllegalStateException(const PandaString &msg)
96 {
97 auto *thread = ManagedThread::GetCurrent();
98 auto ctx = GetLanguageContext(thread);
99 ThrowException(ctx, thread, ctx.GetIllegalStateExceptionClassDescriptor(), utf::CStringAsMutf8(msg.c_str()));
100 }
101
ThrowStringIndexOutOfBoundsException(coretypes::array_ssize_t idx,coretypes::array_size_t length)102 void ThrowStringIndexOutOfBoundsException(coretypes::array_ssize_t idx, coretypes::array_size_t length)
103 {
104 auto *thread = ManagedThread::GetCurrent();
105 auto ctx = GetLanguageContext(thread);
106
107 PandaString msg;
108 msg = "idx = " + ToPandaString(idx) + "; length = " + ToPandaString(length);
109
110 ThrowException(ctx, thread, ctx.GetStringIndexOutOfBoundsExceptionClassDescriptor(),
111 utf::CStringAsMutf8(msg.c_str()));
112 }
113
ThrowNegativeArraySizeException(coretypes::array_ssize_t size)114 void ThrowNegativeArraySizeException(coretypes::array_ssize_t size)
115 {
116 auto *thread = ManagedThread::GetCurrent();
117 auto ctx = GetLanguageContext(thread);
118
119 PandaString msg;
120 msg = "size = " + ToPandaString(size);
121
122 ThrowException(ctx, thread, ctx.GetNegativeArraySizeExceptionClassDescriptor(), utf::CStringAsMutf8(msg.c_str()));
123 }
124
ThrowNegativeArraySizeException(const PandaString & msg)125 void ThrowNegativeArraySizeException(const PandaString &msg)
126 {
127 auto *thread = ManagedThread::GetCurrent();
128 auto ctx = GetLanguageContext(thread);
129 ThrowException(ctx, thread, ctx.GetNegativeArraySizeExceptionClassDescriptor(), utf::CStringAsMutf8(msg.c_str()));
130 }
131
ThrowArithmeticException()132 void ThrowArithmeticException()
133 {
134 auto *thread = ManagedThread::GetCurrent();
135 auto ctx = GetLanguageContext(thread);
136 ThrowException(ctx, thread, ctx.GetArithmeticExceptionClassDescriptor(), utf::CStringAsMutf8("/ by zero"));
137 }
138
ThrowClassCastException(Class * dst_type,Class * src_type)139 void ThrowClassCastException(Class *dst_type, Class *src_type)
140 {
141 auto *thread = ManagedThread::GetCurrent();
142 auto ctx = GetLanguageContext(thread);
143
144 PandaString msg;
145 msg = src_type->GetName() + " cannot be cast to " + dst_type->GetName();
146
147 ThrowException(ctx, thread, ctx.GetClassCastExceptionClassDescriptor(), utf::CStringAsMutf8(msg.c_str()));
148 }
149
ThrowAbstractMethodError(Method * method)150 void ThrowAbstractMethodError(Method *method)
151 {
152 auto *thread = ManagedThread::GetCurrent();
153 auto ctx = GetLanguageContext(thread);
154
155 PandaString msg;
156 msg = "abstract method \"" + method->GetClass()->GetName() + ".";
157 msg += utf::Mutf8AsCString(method->GetName().data);
158 msg += "\"";
159
160 ThrowException(ctx, thread, ctx.GetAbstractMethodErrorClassDescriptor(), utf::CStringAsMutf8(msg.c_str()));
161 }
162
ThrowArrayStoreException(Class * array_class,Class * element_class)163 void ThrowArrayStoreException(Class *array_class, Class *element_class)
164 {
165 PandaStringStream ss;
166 ss << element_class->GetName() << " cannot be stored in an array of type " << array_class->GetName();
167 ThrowArrayStoreException(ss.str());
168 }
169
ThrowArrayStoreException(const PandaString & msg)170 void ThrowArrayStoreException(const PandaString &msg)
171 {
172 auto *thread = ManagedThread::GetCurrent();
173 auto ctx = GetLanguageContext(thread);
174
175 ThrowException(ctx, thread, ctx.GetArrayStoreExceptionClassDescriptor(), utf::CStringAsMutf8(msg.c_str()));
176 }
177
ThrowRuntimeException(const PandaString & msg)178 void ThrowRuntimeException(const PandaString &msg)
179 {
180 auto *thread = ManagedThread::GetCurrent();
181 auto ctx = GetLanguageContext(thread);
182
183 ThrowException(ctx, thread, ctx.GetRuntimeExceptionClassDescriptor(), utf::CStringAsMutf8(msg.c_str()));
184 }
185
ThrowIllegalArgumentException(const PandaString & msg)186 void ThrowIllegalArgumentException(const PandaString &msg)
187 {
188 auto *thread = ManagedThread::GetCurrent();
189 auto ctx = GetLanguageContext(thread);
190
191 ThrowException(ctx, thread, ctx.GetIllegalArgumentExceptionClassDescriptor(), utf::CStringAsMutf8(msg.c_str()));
192 }
193
ThrowClassCircularityError(const PandaString & class_name,LanguageContext ctx)194 void ThrowClassCircularityError(const PandaString &class_name, LanguageContext ctx)
195 {
196 auto *thread = ManagedThread::GetCurrent();
197 PandaString msg = "Class or interface \"" + class_name + "\" is its own superclass or superinterface";
198 ThrowException(ctx, thread, ctx.GetClassCircularityErrorDescriptor(), utf::CStringAsMutf8(msg.c_str()));
199 }
200
201 // NOLINTNEXTLINE(google-runtime-references)
FindCatchBlockInCFrames(ObjectHeader * exception,StackWalker * stack,Frame * orig_frame)202 NO_ADDRESS_SANITIZE void FindCatchBlockInCFrames([[maybe_unused]] ObjectHeader *exception,
203 [[maybe_unused]] StackWalker *stack,
204 [[maybe_unused]] Frame *orig_frame)
205 {
206 }
207
FindCatchBlockInCallStack(ObjectHeader * exception)208 NO_ADDRESS_SANITIZE void FindCatchBlockInCallStack(ObjectHeader *exception)
209 {
210 StackWalker stack(ManagedThread::GetCurrent());
211 auto orig_frame = stack.GetIFrame();
212 ASSERT(!stack.IsCFrame());
213 LOG(DEBUG, INTEROP) << "Enter in FindCatchBlockInCallStack for " << orig_frame->GetMethod()->GetFullName();
214 // Exception thrown from static constructor should be wrapped by the ExceptionInInitializerError
215 if (stack.GetMethod()->IsStaticConstructor()) {
216 return;
217 }
218
219 stack.NextFrame();
220
221 // JNI frames can handle exceptions as well
222 if (!stack.HasFrame() || !stack.IsCFrame() || stack.GetCFrame().IsJni()) {
223 return;
224 }
225 FindCatchBlockInCFrames(exception, &stack, orig_frame);
226 }
227
ThrowFileNotFoundException(const PandaString & msg)228 void ThrowFileNotFoundException(const PandaString &msg)
229 {
230 auto *thread = ManagedThread::GetCurrent();
231 auto ctx = GetLanguageContext(thread);
232
233 ThrowException(ctx, thread, ctx.GetFileNotFoundExceptionClassDescriptor(), utf::CStringAsMutf8(msg.c_str()));
234 }
235
ThrowIOException(const PandaString & msg)236 void ThrowIOException(const PandaString &msg)
237 {
238 auto *thread = ManagedThread::GetCurrent();
239 auto ctx = GetLanguageContext(thread);
240
241 ThrowException(ctx, thread, ctx.GetIOExceptionClassDescriptor(), utf::CStringAsMutf8(msg.c_str()));
242 }
243
ThrowIllegalAccessException(const PandaString & msg)244 void ThrowIllegalAccessException(const PandaString &msg)
245 {
246 auto *thread = ManagedThread::GetCurrent();
247 auto ctx = GetLanguageContext(thread);
248
249 ThrowException(ctx, thread, ctx.GetIllegalAccessExceptionClassDescriptor(), utf::CStringAsMutf8(msg.c_str()));
250 }
251
ThrowOutOfMemoryError(ManagedThread * thread,const PandaString & msg)252 void ThrowOutOfMemoryError(ManagedThread *thread, const PandaString &msg)
253 {
254 auto ctx = GetLanguageContext(thread);
255
256 if (thread->IsThrowingOOM()) {
257 thread->SetUsePreAllocObj(true);
258 }
259
260 thread->SetThrowingOOM(true);
261 ThrowException(ctx, thread, ctx.GetOutOfMemoryErrorClassDescriptor(), utf::CStringAsMutf8(msg.c_str()));
262 thread->SetThrowingOOM(false);
263 }
264
ThrowOutOfMemoryError(const PandaString & msg)265 void ThrowOutOfMemoryError(const PandaString &msg)
266 {
267 auto *thread = ManagedThread::GetCurrent();
268 ThrowOutOfMemoryError(thread, msg);
269 }
270
ThrowUnsupportedOperationException()271 void ThrowUnsupportedOperationException()
272 {
273 auto *thread = ManagedThread::GetCurrent();
274 auto ctx = GetLanguageContext(thread);
275 ThrowException(ctx, thread, ctx.GetUnsupportedOperationExceptionClassDescriptor(), nullptr);
276 }
277
ThrowVerificationException(const PandaString & msg)278 void ThrowVerificationException(const PandaString &msg)
279 {
280 auto *thread = ManagedThread::GetCurrent();
281 auto ctx = GetLanguageContext(thread);
282
283 ThrowException(ctx, thread, ctx.GetVerifyErrorClassDescriptor(), utf::CStringAsMutf8(msg.c_str()));
284 }
285
ThrowVerificationException(LanguageContext ctx,const PandaString & msg)286 void ThrowVerificationException(LanguageContext ctx, const PandaString &msg)
287 {
288 auto *thread = ManagedThread::GetCurrent();
289
290 ThrowException(ctx, thread, ctx.GetVerifyErrorClassDescriptor(), utf::CStringAsMutf8(msg.c_str()));
291 }
292
ThrowInstantiationError(const PandaString & msg)293 void ThrowInstantiationError(const PandaString &msg)
294 {
295 auto *thread = ManagedThread::GetCurrent();
296 auto ctx = GetLanguageContext(thread);
297
298 ThrowException(ctx, thread, ctx.GetInstantiationErrorDescriptor(), utf::CStringAsMutf8(msg.c_str()));
299 }
300
ThrowNoClassDefFoundError(const PandaString & msg)301 void ThrowNoClassDefFoundError(const PandaString &msg)
302 {
303 auto *thread = ManagedThread::GetCurrent();
304 auto ctx = GetLanguageContext(thread);
305
306 ThrowException(ctx, thread, ctx.GetNoClassDefFoundErrorDescriptor(), utf::CStringAsMutf8(msg.c_str()));
307 }
308
ThrowTypedErrorDyn(const std::string & msg)309 void ThrowTypedErrorDyn(const std::string &msg)
310 {
311 auto *thread = ManagedThread::GetCurrent();
312 auto ctx = GetLanguageContext(thread);
313 ThrowException(ctx, thread, ctx.GetTypedErrorDescriptor(), utf::CStringAsMutf8(msg.c_str()));
314 }
315
ThrowReferenceErrorDyn(const std::string & msg)316 void ThrowReferenceErrorDyn(const std::string &msg)
317 {
318 auto *thread = ManagedThread::GetCurrent();
319 auto ctx = GetLanguageContext(thread);
320 ThrowException(ctx, thread, ctx.GetReferenceErrorDescriptor(), utf::CStringAsMutf8(msg.c_str()));
321 }
322
ThrowIllegalMonitorStateException(const PandaString & msg)323 void ThrowIllegalMonitorStateException(const PandaString &msg)
324 {
325 auto *thread = ManagedThread::GetCurrent();
326 auto ctx = GetLanguageContext(thread);
327
328 ThrowException(ctx, thread, ctx.GetIllegalMonitorStateExceptionDescriptor(), utf::CStringAsMutf8(msg.c_str()));
329 }
330
331 } // namespace panda
332