• 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 "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