Exception.cpp revision 9b598e34e2401bda77fca9c8f3a5c50e882e6d68
1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License.
6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at
7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and
14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License.
15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Exception handling.
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "Dalvik.h"
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "libdex/DexCatch.h"
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <stdlib.h>
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectNotes on Exception Handling
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectWe have one fairly sticky issue to deal with: creating the exception stack
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttrace.  The trouble is that we need the current value of the program
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectcounter for the method now being executed, but that's only held in a local
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvariable or hardware register in the main interpreter loop.
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectThe exception mechanism requires that the current stack trace be associated
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectwith a Throwable at the time the Throwable is constructed.  The construction
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectmay or may not be associated with a throw.  We have three situations to
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectconsider:
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (1) A Throwable is created with a "new Throwable" statement in the
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     application code, for immediate or deferred use with a "throw" statement.
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (2) The VM throws an exception from within the interpreter core, e.g.
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     after an integer divide-by-zero.
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (3) The VM throws an exception from somewhere deeper down, e.g. while
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     trying to link a class.
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectWe need to have the current value for the PC, which means that for
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectsituation (3) the interpreter loop must copy it to an externally-accessible
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectlocation before handling any opcode that could cause the VM to throw
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectan exception.  We can't store it globally, because the various threads
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectwould trample each other.  We can't store it in the Thread structure,
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbecause it'll get overwritten as soon as the Throwable constructor starts
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectexecuting.  It needs to go on the stack, but our stack frames hold the
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectcaller's *saved* PC, not the current PC.
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectSituation #1 doesn't require special handling.  Situation #2 could be dealt
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectwith by passing the PC into the exception creation function.  The trick
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectis to solve situation #3 in a way that adds minimal overhead to common
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectoperations.  Making it more costly to throw an exception is acceptable.
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectThere are a few ways to deal with this:
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (a) Change "savedPc" to "currentPc" in the stack frame.  All of the
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     stack logic gets offset by one frame.  The current PC is written
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     to the current stack frame when necessary.
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (b) Write the current PC into the current stack frame, but without
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     replacing "savedPc".  The JNI local refs pointer, which is only
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     used for native code, can be overloaded to save space.
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (c) In dvmThrowException(), push an extra stack frame on, with the
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     current PC in it.  The current PC is written into the Thread struct
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     when necessary, and copied out when the VM throws.
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (d) Before doing something that might throw an exception, push a
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     temporary frame on with the saved PC in it.
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectSolution (a) is the simplest, but breaks Dalvik's goal of mingling native
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectand interpreted stacks.
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectSolution (b) retains the simplicity of (a) without rearranging the stack,
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbut now in some cases we're storing the PC twice, which feels wrong.
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectSolution (c) usually works, because we push the saved PC onto the stack
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbefore the Throwable construction can overwrite the copy in Thread.  One
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectway solution (c) could break is:
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project - Interpreter saves the PC
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project - Execute some bytecode, which runs successfully (and alters the saved PC)
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project - Throw an exception before re-saving the PC (i.e in the same opcode)
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectThis is a risk for anything that could cause <clinit> to execute, e.g.
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectexecuting a static method or accessing a static field.  Attemping to access
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecta field that doesn't exist in a class that does exist might cause this.
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectIt may be possible to simply bracket the dvmCallMethod*() functions to
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectsave/restore it.
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectSolution (d) incurs additional overhead, but may have other benefits (e.g.
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectit's easy to find the stack frames that should be removed before storage
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectin the Throwable).
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectCurrent plan is option (b), because it's simple, fast, and doesn't change
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectthe way the stack works.
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project*/
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* fwd */
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool initException(Object* exception, const char* msg, Object* cause,
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Thread* self);
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
10432bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein * Helper for dvmExceptionStartup(), which looks up classes and stores
10532bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein * them to the indicated pointer, returning a failure code (false ==
10632bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein * failure).
10732bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein */
10832bb3da6f05959749161ce7f9103027f11597fe3Dan Bornsteinstatic bool initRef(ClassObject** pClass, const char* name)
10932bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein{
11032bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein    ClassObject* result;
11132bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein
11232bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein    if (name[0] == '[') {
11332bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein        result = dvmFindArrayClass(name, NULL);
11432bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein    } else {
11532bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein        result = dvmFindSystemClassNoInit(name);
11632bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein    }
11732bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein
11832bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein    if (result == NULL) {
11932bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein        LOGE("Could not find exception class %s\n", name);
12032bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein        return false;
12132bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein    }
12232bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein
12332bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein    *pClass = result;
12432bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein    return true;
12532bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein}
12632bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein
12732bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein/*
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Cache pointers to some of the exception classes we use locally.
129686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden *
130686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden * Note this is NOT called during dexopt optimization.  Some of the fields
131686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden * are initialized by the verifier (dvmVerifyCodeFlow).
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmExceptionStartup(void)
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
13532bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein    bool ok = true;
13632bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein
1376d167a4b02f310700a55fc9a24fccce999e0fdf2Dan Bornstein    ok &= initRef(&gDvm.exArithmeticException,
1386d167a4b02f310700a55fc9a24fccce999e0fdf2Dan Bornstein            "Ljava/lang/ArithmeticException;");
1396d167a4b02f310700a55fc9a24fccce999e0fdf2Dan Bornstein    ok &= initRef(&gDvm.exArrayIndexOutOfBoundsException,
1406d167a4b02f310700a55fc9a24fccce999e0fdf2Dan Bornstein            "Ljava/lang/ArrayIndexOutOfBoundsException;");
1416d167a4b02f310700a55fc9a24fccce999e0fdf2Dan Bornstein    ok &= initRef(&gDvm.exArrayStoreException,
1426d167a4b02f310700a55fc9a24fccce999e0fdf2Dan Bornstein            "Ljava/lang/ArrayStoreException;");
1436d167a4b02f310700a55fc9a24fccce999e0fdf2Dan Bornstein    ok &= initRef(&gDvm.exClassCastException,
1446d167a4b02f310700a55fc9a24fccce999e0fdf2Dan Bornstein            "Ljava/lang/ClassCastException;");
1459b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein    ok &= initRef(&gDvm.exClassNotFoundException,
1469b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein            "Ljava/lang/ClassNotFoundException;");
1472c8e25b2010d1bba4dca0148691bc6e1a4ee7616Dan Bornstein    ok &= initRef(&gDvm.exClassFormatError, "Ljava/lang/ClassFormatError;");
14832bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein    ok &= initRef(&gDvm.exError, "Ljava/lang/Error;");
14932bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein    ok &= initRef(&gDvm.exExceptionInInitializerError,
15032bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein            "Ljava/lang/ExceptionInInitializerError;");
1512c8e25b2010d1bba4dca0148691bc6e1a4ee7616Dan Bornstein    ok &= initRef(&gDvm.exFileNotFoundException,
1522c8e25b2010d1bba4dca0148691bc6e1a4ee7616Dan Bornstein            "Ljava/io/FileNotFoundException;");
1532c8e25b2010d1bba4dca0148691bc6e1a4ee7616Dan Bornstein    ok &= initRef(&gDvm.exIOException, "Ljava/io/IOException;");
1549b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein    ok &= initRef(&gDvm.exIllegalAccessException,
1559b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein            "Ljava/lang/IllegalAccessException;");
1569b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein    ok &= initRef(&gDvm.exInterruptedException,
1579b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein            "Ljava/lang/InterruptedException;");
1582c8e25b2010d1bba4dca0148691bc6e1a4ee7616Dan Bornstein    ok &= initRef(&gDvm.exNegativeArraySizeException,
1592c8e25b2010d1bba4dca0148691bc6e1a4ee7616Dan Bornstein            "Ljava/lang/NegativeArraySizeException;");
1609b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein    ok &= initRef(&gDvm.exNoSuchFieldException,
1619b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein            "Ljava/lang/NoSuchFieldException;");
1622c8e25b2010d1bba4dca0148691bc6e1a4ee7616Dan Bornstein    ok &= initRef(&gDvm.exNullPointerException,
1632c8e25b2010d1bba4dca0148691bc6e1a4ee7616Dan Bornstein            "Ljava/lang/NullPointerException;");
16432bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein    ok &= initRef(&gDvm.exRuntimeException, "Ljava/lang/RuntimeException;");
16532bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein    ok &= initRef(&gDvm.exStackOverflowError,
16632bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein            "Ljava/lang/StackOverflowError;");
1679b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein    ok &= initRef(&gDvm.exStaleDexCacheError,
1689b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein            "Ldalvik/system/StaleDexCacheError;");
1697a86c44bde10b37d8df17d0613072c4ef134189cDan Bornstein    ok &= initRef(&gDvm.exStringIndexOutOfBoundsException,
1707a86c44bde10b37d8df17d0613072c4ef134189cDan Bornstein            "Ljava/lang/StringIndexOutOfBoundsException;");
17132bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein    ok &= initRef(&gDvm.exThrowable, "Ljava/lang/Throwable;");
1727a86c44bde10b37d8df17d0613072c4ef134189cDan Bornstein    ok &= initRef(&gDvm.exUnsupportedOperationException,
1737a86c44bde10b37d8df17d0613072c4ef134189cDan Bornstein            "Ljava/lang/UnsupportedOperationException;");
1747a86c44bde10b37d8df17d0613072c4ef134189cDan Bornstein    ok &= initRef(&gDvm.exVirtualMachineError,
1757a86c44bde10b37d8df17d0613072c4ef134189cDan Bornstein            "Ljava/lang/VirtualMachineError;");
1767a86c44bde10b37d8df17d0613072c4ef134189cDan Bornstein
17732bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein    ok &= initRef(&gDvm.classJavaLangStackTraceElement,
17832bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein            "Ljava/lang/StackTraceElement;");
17932bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein    ok &= initRef(&gDvm.classJavaLangStackTraceElementArray,
18032bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein            "[Ljava/lang/StackTraceElement;");
18132bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein
18232bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein    if (!ok) {
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Find the constructor.  Note that, unlike other saved method lookups,
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * we're using a Method* instead of a vtable offset.  This is because
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * constructors don't have vtable offsets.  (Also, since we're creating
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the object in question, it's impossible for anyone to sub-class it.)
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Method* meth;
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    meth = dvmFindDirectMethodByDescriptor(gDvm.classJavaLangStackTraceElement,
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        "<init>", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V");
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (meth == NULL) {
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGE("Unable to find constructor for StackTraceElement\n");
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.methJavaLangStackTraceElement_init = meth;
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* grab an offset for the stackData field */
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.offJavaLangThrowable_stackState =
20332bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein        dvmFindFieldOffset(gDvm.exThrowable,
204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "stackState", "Ljava/lang/Object;");
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.offJavaLangThrowable_stackState < 0) {
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGE("Unable to find Throwable.stackState\n");
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* and one for the cause field, just 'cause */
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.offJavaLangThrowable_cause =
21232bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein        dvmFindFieldOffset(gDvm.exThrowable,
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "cause", "Ljava/lang/Throwable;");
214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.offJavaLangThrowable_cause < 0) {
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGE("Unable to find Throwable.cause\n");
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
21932bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein    /*
22032bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein     * ExceptionInInitializerError is used in the guts of Class.c; it
22132bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein     * wants to call the constructor more directly, so look that up
22232bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein     * explicitly, here.
22332bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein     */
22432bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein    gDvm.methJavaLangExceptionInInitializerError_init =
22532bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein        dvmFindDirectMethodByDescriptor(gDvm.exExceptionInInitializerError,
22632bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein            "<init>", "(Ljava/lang/Throwable;)V");
22732bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein    if (gDvm.methJavaLangExceptionInInitializerError_init == NULL) {
22832bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein        LOGE("Unable to prep java/lang/ExceptionInInitializerError\n");
22932bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein        return false;
23032bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein    }
23132bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein
232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Clean up.
237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmExceptionShutdown(void)
239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // nothing to do
241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2450171812e59e2520a4345b9bbadd4f7afa0a1de16Andy McFadden * Format the message into a small buffer and pass it along.
2460171812e59e2520a4345b9bbadd4f7afa0a1de16Andy McFadden */
2470171812e59e2520a4345b9bbadd4f7afa0a1de16Andy McFaddenvoid dvmThrowExceptionFmtV(const char* exceptionDescriptor, const char* fmt,
2480171812e59e2520a4345b9bbadd4f7afa0a1de16Andy McFadden    va_list args)
2490171812e59e2520a4345b9bbadd4f7afa0a1de16Andy McFadden{
2500171812e59e2520a4345b9bbadd4f7afa0a1de16Andy McFadden    char msgBuf[512];
2510171812e59e2520a4345b9bbadd4f7afa0a1de16Andy McFadden
2520171812e59e2520a4345b9bbadd4f7afa0a1de16Andy McFadden    vsnprintf(msgBuf, sizeof(msgBuf), fmt, args);
2530171812e59e2520a4345b9bbadd4f7afa0a1de16Andy McFadden    dvmThrowChainedException(exceptionDescriptor, msgBuf, NULL);
2540171812e59e2520a4345b9bbadd4f7afa0a1de16Andy McFadden}
2550171812e59e2520a4345b9bbadd4f7afa0a1de16Andy McFadden
2566d167a4b02f310700a55fc9a24fccce999e0fdf2Dan Bornsteinvoid dvmThrowExceptionFmtByClassV(ClassObject* exceptionClass,
2576d167a4b02f310700a55fc9a24fccce999e0fdf2Dan Bornstein    const char* fmt, va_list args)
2586d167a4b02f310700a55fc9a24fccce999e0fdf2Dan Bornstein{
2596d167a4b02f310700a55fc9a24fccce999e0fdf2Dan Bornstein    char msgBuf[512];
2606d167a4b02f310700a55fc9a24fccce999e0fdf2Dan Bornstein
2616d167a4b02f310700a55fc9a24fccce999e0fdf2Dan Bornstein    vsnprintf(msgBuf, sizeof(msgBuf), fmt, args);
2626d167a4b02f310700a55fc9a24fccce999e0fdf2Dan Bornstein    dvmThrowChainedExceptionByClass(exceptionClass, msgBuf, NULL);
2636d167a4b02f310700a55fc9a24fccce999e0fdf2Dan Bornstein}
2646d167a4b02f310700a55fc9a24fccce999e0fdf2Dan Bornstein
2650171812e59e2520a4345b9bbadd4f7afa0a1de16Andy McFadden/*
266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Create a Throwable and throw an exception in the current thread (where
267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "throwing" just means "set the thread's exception pointer").
268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "msg" and/or "cause" may be NULL.
270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If we have a bad exception hierarchy -- something in Throwable.<init>
272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * is missing -- then every attempt to throw an exception will result
273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * in another exception.  Exceptions are generally allowed to "chain"
274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to other exceptions, so it's hard to auto-detect this problem.  It can
275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * only happen if the system classes are broken, so it's probably not
276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * worth spending cycles to detect it.
277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We do have one case to worry about: if the classpath is completely
279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * wrong, we'll go into a death spin during startup because we can't find
280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the initial class and then we can't find NoClassDefFoundError.  We have
281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to handle this case.
282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * [Do we want to cache pointers to common exception classes?]
284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmThrowChainedException(const char* exceptionDescriptor, const char* msg,
286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object* cause)
287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* excepClass;
289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGV("THROW '%s' msg='%s' cause=%s\n",
291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        exceptionDescriptor, msg,
292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        (cause != NULL) ? cause->clazz->descriptor : "(none)");
293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.initializing) {
295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (++gDvm.initExceptionCount >= 2) {
296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGE("Too many exceptions during init (failed on '%s' '%s')\n",
297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                exceptionDescriptor, msg);
298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmAbort();
299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    excepClass = dvmFindSystemClass(exceptionDescriptor);
303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (excepClass == NULL) {
304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We couldn't find the exception class.  The attempt to find a
306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * nonexistent class should have raised an exception.  If no
307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * exception is currently raised, then we're pretty clearly unable
308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * to throw ANY sort of exception, and we need to pack it in.
309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * If we were able to throw the "class load failed" exception,
311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * stick with that.  Ideally we'd stuff the original exception
312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * into the "cause" field, but since we can't find it we can't
313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * do that.  The exception class name should be in the "message"
314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * field.
315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!dvmCheckException(dvmThreadSelf())) {
317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGE("FATAL: unable to throw exception (failed on '%s' '%s')\n",
318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                exceptionDescriptor, msg);
319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmAbort();
320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmThrowChainedExceptionByClass(excepClass, msg, cause);
325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Start/continue throwing process now that we have a class reference.
329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmThrowChainedExceptionByClass(ClassObject* excepClass, const char* msg,
331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object* cause)
332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Thread* self = dvmThreadSelf();
334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object* exception;
335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3362c8e25b2010d1bba4dca0148691bc6e1a4ee7616Dan Bornstein    if (excepClass == NULL) {
3372c8e25b2010d1bba4dca0148691bc6e1a4ee7616Dan Bornstein        /*
3382c8e25b2010d1bba4dca0148691bc6e1a4ee7616Dan Bornstein         * The exception class was passed in as NULL. This might happen
3392c8e25b2010d1bba4dca0148691bc6e1a4ee7616Dan Bornstein         * early on in VM initialization. There's nothing better to do
3402c8e25b2010d1bba4dca0148691bc6e1a4ee7616Dan Bornstein         * than just log the message as an error and abort.
3412c8e25b2010d1bba4dca0148691bc6e1a4ee7616Dan Bornstein         */
3422c8e25b2010d1bba4dca0148691bc6e1a4ee7616Dan Bornstein        LOGE("Fatal error: %s\n", msg);
3432c8e25b2010d1bba4dca0148691bc6e1a4ee7616Dan Bornstein        dvmAbort();
3442c8e25b2010d1bba4dca0148691bc6e1a4ee7616Dan Bornstein    }
3452c8e25b2010d1bba4dca0148691bc6e1a4ee7616Dan Bornstein
346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* make sure the exception is initialized */
347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!dvmIsClassInitialized(excepClass) && !dvmInitClass(excepClass)) {
348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGE("ERROR: unable to initialize exception class '%s'\n",
349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            excepClass->descriptor);
350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (strcmp(excepClass->descriptor, "Ljava/lang/InternalError;") == 0)
351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmAbort();
352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmThrowChainedException("Ljava/lang/InternalError;",
353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "failed to init original exception class", cause);
354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    exception = dvmAllocObject(excepClass, ALLOC_DEFAULT);
358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (exception == NULL) {
359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We're in a lot of trouble.  We might be in the process of
361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * throwing an out-of-memory exception, in which case the
362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * pre-allocated object will have been thrown when our object alloc
363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * failed.  So long as there's an exception raised, return and
364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * allow the system to try to recover.  If not, something is broken
365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * and we need to bail out.
366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (dvmCheckException(self))
368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGE("FATAL: unable to allocate exception '%s' '%s'\n",
370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            excepClass->descriptor, msg != NULL ? msg : "(no msg)");
371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmAbort();
372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Init the exception.
376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.optimizing) {
378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* need the exception object, but can't invoke interpreted code */
379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGV("Skipping init of exception %s '%s'\n",
380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            excepClass->descriptor, msg);
381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(excepClass == exception->clazz);
383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!initException(exception, msg, cause, self)) {
384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Whoops.  If we can't initialize the exception, we can't use
386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * it.  If there's an exception already set, the constructor
387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * probably threw an OutOfMemoryError.
388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!dvmCheckException(self)) {
390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /*
391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * We're required to throw something, so we just
392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * throw the pre-constructed internal error.
393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                self->exception = gDvm.internalErrorObj;
395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    self->exception = exception;
401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmReleaseTrackedAlloc(exception, self);
404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4075016966b91f1bc36b2bd52ec13ecfd8de1c68209Elliott Hughes * Throw the named exception using the human-readable form of the class
408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * descriptor as the exception message, and with the specified cause.
409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmThrowChainedExceptionWithClassMessage(const char* exceptionDescriptor,
411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* messageDescriptor, Object* cause)
412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
4135016966b91f1bc36b2bd52ec13ecfd8de1c68209Elliott Hughes    char* message = dvmHumanReadableDescriptor(messageDescriptor);
414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmThrowChainedException(exceptionDescriptor, message, cause);
416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(message);
417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
420d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein * Like dvmThrowException, but take a class object instead of a name
421d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein * and turn the given message into the human-readable form for a descriptor.
422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmThrowExceptionByClassWithClassMessage(ClassObject* exceptionClass,
424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* messageDescriptor)
425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* message = dvmDescriptorToName(messageDescriptor);
427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmThrowExceptionByClass(exceptionClass, message);
429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(message);
430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4334a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein * Find and return an exception constructor method that can take the
4344a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein * indicated parameters, or return NULL if no such constructor exists.
4354a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein */
4364a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornsteinstatic Method* findExceptionInitMethod(ClassObject* excepClass,
4374a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein    bool hasMessage, bool hasCause)
4384a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein{
4394a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein    if (hasMessage) {
4404a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein        Method* result;
4414a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein
4424a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein        if (hasCause) {
4434a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein            result = dvmFindDirectMethodByDescriptor(
4444a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein                    excepClass, "<init>",
4454a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein                    "(Ljava/lang/String;Ljava/lang/Throwable;)V");
4464a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein        } else {
4474a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein            result = dvmFindDirectMethodByDescriptor(
4484a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein                    excepClass, "<init>", "(Ljava/lang/String;)V");
4494a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein        }
4504a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein
4514a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein        if (result != NULL) {
4524a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein            return result;
4534a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein        }
4544a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein
4554a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein        if (hasCause) {
4564a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein            return dvmFindDirectMethodByDescriptor(
4574a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein                    excepClass, "<init>",
4584a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein                    "(Ljava/lang/Object;Ljava/lang/Throwable;)V");
4594a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein        } else {
4604a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein            return dvmFindDirectMethodByDescriptor(
4614a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein                    excepClass, "<init>", "(Ljava/lang/Object;)V");
4624a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein        }
4634a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein    } else if (hasCause) {
4644a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein        return dvmFindDirectMethodByDescriptor(
4654a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein                excepClass, "<init>", "(Ljava/lang/Throwable;)V");
4664a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein    } else {
4674a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein        return dvmFindDirectMethodByDescriptor(excepClass, "<init>", "()V");
4684a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein    }
4694a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein}
4704a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein
4714a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein/*
472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Initialize an exception with an appropriate constructor.
473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "exception" is the exception object to initialize.
475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Either or both of "msg" and "cause" may be null.
476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "self" is dvmThreadSelf(), passed in so we don't have to look it up again.
477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If the process of initializing the exception causes another
479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * exception (e.g., OutOfMemoryError) to be thrown, return an error
480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and leave self->exception intact.
481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool initException(Object* exception, const char* msg, Object* cause,
483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Thread* self)
484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    enum {
486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        kInitUnknown,
487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        kInitNoarg,
488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        kInitMsg,
489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        kInitMsgThrow,
490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        kInitThrow
491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } initKind = kInitUnknown;
492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Method* initMethod = NULL;
493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* excepClass = exception->clazz;
494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    StringObject* msgStr = NULL;
495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool result = false;
496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool needInitCause = false;
497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(self != NULL);
499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(self->exception == NULL);
500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* if we have a message, create a String */
502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (msg == NULL)
503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        msgStr = NULL;
504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    else {
50581f3ebe03cd33c9003641084bece0604ee68bf88Barry Hayes        msgStr = dvmCreateStringFromCstr(msg);
506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (msgStr == NULL) {
507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGW("Could not allocate message string \"%s\" while "
508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    "throwing internal exception (%s)\n",
509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    msg, excepClass->descriptor);
510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
514686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden    if (cause != NULL) {
51532bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein        if (!dvmInstanceof(cause->clazz, gDvm.exThrowable)) {
516686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden            LOGE("Tried to init exception with cause '%s'\n",
517686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden                cause->clazz->descriptor);
518686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden            dvmAbort();
519686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden        }
520686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden    }
521686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden
522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The Throwable class has four public constructors:
524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *  (1) Throwable()
525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *  (2) Throwable(String message)
526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *  (3) Throwable(String message, Throwable cause)  (added in 1.4)
527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *  (4) Throwable(Throwable cause)                  (added in 1.4)
528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The first two are part of the original design, and most exception
530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * classes should support them.  The third prototype was used by
531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * individual exceptions. e.g. ClassNotFoundException added it in 1.2.
532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The general "cause" mechanism was added in 1.4.  Some classes,
533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * such as IllegalArgumentException, initially supported the first
534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * two, but added the second two in a later release.
535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Exceptions may be picky about how their "cause" field is initialized.
537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * If you call ClassNotFoundException(String), it may choose to
538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * initialize its "cause" field to null.  Doing so prevents future
539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * calls to Throwable.initCause().
540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * So, if "cause" is not NULL, we need to look for a constructor that
542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * takes a throwable.  If we can't find one, we fall back on calling
543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * #1/#2 and making a separate call to initCause().  Passing a null ref
544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * for "message" into Throwable(String, Throwable) is allowed, but we
545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * prefer to use the Throwable-only version because it has different
546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * behavior.
547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * java.lang.TypeNotPresentException is a strange case -- it has #3 but
549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * not #2.  (Some might argue that the constructor is actually not #3,
550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * because it doesn't take the message string as an argument, but it
551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * has the same effect and we can work with it here.)
5524a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein     *
5534a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein     * java.lang.AssertionError is also a strange case -- it has a
5544a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein     * constructor that takes an Object, but not one that takes a String.
5554a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein     * There may be other cases like this, as well, so we generally look
5564a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein     * for an Object-taking constructor if we can't find one that takes
5574a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein     * a String.
558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (cause == NULL) {
560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (msgStr == NULL) {
5614a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein            initMethod = findExceptionInitMethod(excepClass, false, false);
562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            initKind = kInitNoarg;
563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
5644a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein            initMethod = findExceptionInitMethod(excepClass, true, false);
565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (initMethod != NULL) {
566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                initKind = kInitMsg;
567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* no #2, try #3 */
5694a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein                initMethod = findExceptionInitMethod(excepClass, true, true);
5704a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein                if (initMethod != NULL) {
571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    initKind = kInitMsgThrow;
5724a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein                }
573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (msgStr == NULL) {
5774a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein            initMethod = findExceptionInitMethod(excepClass, false, true);
578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (initMethod != NULL) {
579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                initKind = kInitThrow;
580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
5814a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein                initMethod = findExceptionInitMethod(excepClass, false, false);
582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                initKind = kInitNoarg;
583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                needInitCause = true;
584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
5864a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein            initMethod = findExceptionInitMethod(excepClass, true, true);
587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (initMethod != NULL) {
588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                initKind = kInitMsgThrow;
589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
5904a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein                initMethod = findExceptionInitMethod(excepClass, true, false);
591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                initKind = kInitMsg;
592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                needInitCause = true;
593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (initMethod == NULL) {
598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We can't find the desired constructor.  This can happen if a
600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * subclass of java/lang/Throwable doesn't define an expected
601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * constructor, e.g. it doesn't provide one that takes a string
602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * when a message has been provided.
603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("WARNING: exception class '%s' missing constructor "
605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "(msg='%s' kind=%d)\n",
606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            excepClass->descriptor, msg, initKind);
607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(strcmp(excepClass->descriptor,
608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                      "Ljava/lang/RuntimeException;") != 0);
60932bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein        dvmThrowChainedExceptionByClass(gDvm.exRuntimeException,
610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "re-throw on exception class missing constructor", NULL);
611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Call the constructor with the appropriate arguments.
616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    JValue unused;
618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    switch (initKind) {
619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kInitNoarg:
620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("+++ exc noarg (ic=%d)\n", needInitCause);
621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmCallMethod(self, initMethod, exception, &unused);
622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kInitMsg:
624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("+++ exc msg (ic=%d)\n", needInitCause);
625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmCallMethod(self, initMethod, exception, &unused, msgStr);
626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kInitThrow:
628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("+++ exc throw");
629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(!needInitCause);
630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmCallMethod(self, initMethod, exception, &unused, cause);
631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kInitMsgThrow:
633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("+++ exc msg+throw");
634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(!needInitCause);
635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmCallMethod(self, initMethod, exception, &unused, msgStr, cause);
636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    default:
638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(false);
639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * It's possible the constructor has thrown an exception.  If so, we
644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * return an error and let our caller deal with it.
645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (self->exception != NULL) {
647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("Exception thrown (%s) while throwing internal exception (%s)\n",
648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            self->exception->clazz->descriptor, exception->clazz->descriptor);
649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * If this exception was caused by another exception, and we weren't
654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * able to find a cause-setting constructor, set the "cause" field
655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * with an explicit call.
656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (needInitCause) {
658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Method* initCause;
659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        initCause = dvmFindVirtualMethodHierByDescriptor(excepClass, "initCause",
660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "(Ljava/lang/Throwable;)Ljava/lang/Throwable;");
661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (initCause != NULL) {
662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmCallMethod(self, initCause, exception, &unused, cause);
663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (self->exception != NULL) {
664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* initCause() threw an exception; return an error and
665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * let the caller deal with it.
666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOGW("Exception thrown (%s) during initCause() "
668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        "of internal exception (%s)\n",
669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        self->exception->clazz->descriptor,
670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        exception->clazz->descriptor);
671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                goto bail;
672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGW("WARNING: couldn't find initCause in '%s'\n",
675f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                excepClass->descriptor);
676f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
679f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    result = true;
681f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
683f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmReleaseTrackedAlloc((Object*) msgStr, self);     // NULL is ok
684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return result;
685f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Clear the pending exception and the "initExceptionCount" counter.  This
690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * is used by the optimization and verification code, which has to run with
691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "initializing" set to avoid going into a death-spin if the "class not
692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * found" exception can't be found.
693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This can also be called when the VM is in a "normal" state, e.g. when
695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * verifying classes that couldn't be verified at optimization time.  The
696f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * reset of initExceptionCount should be harmless in that case.
697f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmClearOptException(Thread* self)
699f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
700f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    self->exception = NULL;
701f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.initExceptionCount = 0;
702f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
703f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
704f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
705f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns "true" if this is a "checked" exception, i.e. it's a subclass
706f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * of Throwable (assumed) but not a subclass of RuntimeException or Error.
707f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
708f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmIsCheckedException(const Object* exception)
709f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
71032bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein    if (dvmInstanceof(exception->clazz, gDvm.exError) ||
71132bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein        dvmInstanceof(exception->clazz, gDvm.exRuntimeException))
712f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
714f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
715f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return true;
716f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
718f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
720f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Wrap the now-pending exception in a different exception.  This is useful
721f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * for reflection stuff that wants to hand a checked exception back from a
722f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * method that doesn't declare it.
723f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If something fails, an (unchecked) exception related to that failure
725f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * will be pending instead.
726f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmWrapException(const char* newExcepStr)
728f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Thread* self = dvmThreadSelf();
730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object* origExcep;
731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* iteClass;
732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
733f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    origExcep = dvmGetException(self);
734f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmAddTrackedAlloc(origExcep, self);    // don't let the GC free it
735f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
736f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmClearException(self);                // clear before class lookup
737f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    iteClass = dvmFindSystemClass(newExcepStr);
738f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (iteClass != NULL) {
739f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Object* iteExcep;
740f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Method* initMethod;
741f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
742f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        iteExcep = dvmAllocObject(iteClass, ALLOC_DEFAULT);
743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (iteExcep != NULL) {
744f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            initMethod = dvmFindDirectMethodByDescriptor(iteClass, "<init>",
745f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            "(Ljava/lang/Throwable;)V");
746f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (initMethod != NULL) {
747f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                JValue unused;
748f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmCallMethod(self, initMethod, iteExcep, &unused,
749f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    origExcep);
750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
751f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* if <init> succeeded, replace the old exception */
752f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (!dvmCheckException(self))
753f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    dvmSetException(self, iteExcep);
754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmReleaseTrackedAlloc(iteExcep, NULL);
756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* if initMethod doesn't exist, or failed... */
758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!dvmCheckException(self))
759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmSetException(self, origExcep);
760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* leave OutOfMemoryError pending */
762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* leave ClassNotFoundException pending */
765f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
766f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
767f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(dvmCheckException(self));
768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmReleaseTrackedAlloc(origExcep, self);
769f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
770f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
771f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
772686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden * Get the "cause" field from an exception.
773686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden *
774686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden * The Throwable class initializes the "cause" field to "this" to
775686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden * differentiate between being initialized to null and never being
776686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden * initialized.  We check for that here and convert it to NULL.
777686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden */
778686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFaddenObject* dvmGetExceptionCause(const Object* exception)
779686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden{
78032bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein    if (!dvmInstanceof(exception->clazz, gDvm.exThrowable)) {
781686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden        LOGE("Tried to get cause from object of type '%s'\n",
782686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden            exception->clazz->descriptor);
783686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden        dvmAbort();
784686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden    }
785686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden    Object* cause =
786686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden        dvmGetFieldObject(exception, gDvm.offJavaLangThrowable_cause);
787686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden    if (cause == exception)
788686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden        return NULL;
789686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden    else
790686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden        return cause;
791686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden}
792686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden
793686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden/*
794f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Print the stack trace of the current exception on stderr.  This is called
795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * from the JNI ExceptionDescribe call.
796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * For consistency we just invoke the Throwable printStackTrace method,
798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * which might be overridden in the exception object.
799f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Exceptions thrown during the course of printing the stack trace are
801f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ignored.
802f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
803f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmPrintExceptionStackTrace(void)
804f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Thread* self = dvmThreadSelf();
806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object* exception;
807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Method* printMethod;
808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    exception = self->exception;
810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (exception == NULL)
811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
81350cab51bb381c5da01adfd61954ddca37607f51eAndy McFadden    dvmAddTrackedAlloc(exception, self);
814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    self->exception = NULL;
815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printMethod = dvmFindVirtualMethodHierByDescriptor(exception->clazz,
816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    "printStackTrace", "()V");
817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (printMethod != NULL) {
818f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        JValue unused;
819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmCallMethod(self, printMethod, exception, &unused);
820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
821f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("WARNING: could not find printStackTrace in %s\n",
822f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            exception->clazz->descriptor);
823f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
824f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
825f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (self->exception != NULL) {
82622680eee4aa012c839568d83a132b2b20ff39525Elliott Hughes        LOGW("NOTE: exception thrown while printing stack trace: %s\n",
827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            self->exception->clazz->descriptor);
828f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
829f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
830f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    self->exception = exception;
83150cab51bb381c5da01adfd61954ddca37607f51eAndy McFadden    dvmReleaseTrackedAlloc(exception, self);
832f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
834f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
835f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Search the method's list of exceptions for a match.
836f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
837f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns the offset of the catch block on success, or -1 on failure.
838f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
839f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int findCatchInMethod(Thread* self, const Method* method, int relPc,
840f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* excepClass)
841f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
842f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
843f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Need to clear the exception before entry.  Otherwise, dvmResolveClass
844f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * might think somebody threw an exception while it was loading a class.
845f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
846f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(!dvmCheckException(self));
847f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(!dvmIsNativeMethod(method));
848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGVV("findCatchInMethod %s.%s excep=%s depth=%d\n",
850f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        method->clazz->descriptor, method->name, excepClass->descriptor,
851f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmComputeExactFrameDepth(self->curFrame));
852f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
853f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DvmDex* pDvmDex = method->clazz->pDvmDex;
854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexCode* pCode = dvmGetMethodCode(method);
855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DexCatchIterator iterator;
856f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dexFindCatchHandler(&iterator, pCode, relPc)) {
858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (;;) {
859f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            DexCatchHandler* handler = dexCatchIteratorNext(&iterator);
860f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (handler == NULL) {
862f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
863f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
864de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
865f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (handler->typeIdx == kDexNoIndex) {
866f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* catch-all */
867f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOGV("Match on catch-all block at 0x%02x in %s.%s for %s\n",
868f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        relPc, method->clazz->descriptor,
869f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        method->name, excepClass->descriptor);
870f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return handler->address;
871f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
872f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
873f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ClassObject* throwable =
874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmDexGetResolvedClass(pDvmDex, handler->typeIdx);
875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (throwable == NULL) {
876f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /*
877f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * TODO: this behaves badly if we run off the stack
878f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * while trying to throw an exception.  The problem is
879f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * that, if we're in a class loaded by a class loader,
880f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * the call to dvmResolveClass has to ask the class
881f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * loader for help resolving any previously-unresolved
882f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * classes.  If this particular class loader hasn't
883f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * resolved StackOverflowError, it will call into
884f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * interpreted code, and blow up.
885f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 *
886f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * We currently replace the previous exception with
887f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * the StackOverflowError, which means they won't be
888f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * catching it *unless* they explicitly catch
889f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * StackOverflowError, in which case we'll be unable
890f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * to resolve the class referred to by the "catch"
891f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * block.
892f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 *
893f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * We end up getting a huge pile of warnings if we do
894f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * a simple synthetic test, because this method gets
895f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * called on every stack frame up the tree, and it
896f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * fails every time.
897f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 *
898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * This eventually bails out, effectively becoming an
899f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * uncatchable exception, so other than the flurry of
900f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * warnings it's not really a problem.  Still, we could
901f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * probably handle this better.
902f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
903f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                throwable = dvmResolveClass(method->clazz, handler->typeIdx,
904f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    true);
905f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (throwable == NULL) {
906f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    /*
907f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     * We couldn't find the exception they wanted in
908f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     * our class files (or, perhaps, the stack blew up
909f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     * while we were querying a class loader). Cough
910f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     * up a warning, then move on to the next entry.
911f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     * Keep the exception status clear.
912f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     */
913f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LOGW("Could not resolve class ref'ed in exception "
914f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            "catch list (class index %d, exception %s)\n",
915f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            handler->typeIdx,
916f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            (self->exception != NULL) ?
917f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            self->exception->clazz->descriptor : "(none)");
918f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    dvmClearException(self);
919f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    continue;
920f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
921f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
922f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
923f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //LOGD("ADDR MATCH, check %s instanceof %s\n",
924f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //    excepClass->descriptor, pEntry->excepClass->descriptor);
925f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
926f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (dvmInstanceof(excepClass, throwable)) {
927f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOGV("Match on catch block at 0x%02x in %s.%s for %s\n",
928f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        relPc, method->clazz->descriptor,
929f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        method->name, excepClass->descriptor);
930f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return handler->address;
931f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
932f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
933f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
934f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
935f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGV("No matching catch block at 0x%02x in %s for %s\n",
936f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        relPc, method->name, excepClass->descriptor);
937f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return -1;
938f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
939f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
940f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
941f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Find a matching "catch" block.  "pc" is the relative PC within the
942f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * current method, indicating the offset from the start in 16-bit units.
943f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
944f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns the offset to the catch block, or -1 if we run up against a
945f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * break frame without finding anything.
946f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
947f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The class resolution stuff we have to do while evaluating the "catch"
948f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * blocks could cause an exception.  The caller should clear the exception
949f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * before calling here and restore it after.
950f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
951f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Sets *newFrame to the frame pointer of the frame with the catch block.
952f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If "scanOnly" is false, self->curFrame is also set to this value.
953f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
954f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint dvmFindCatchBlock(Thread* self, int relPc, Object* exception,
955f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool scanOnly, void** newFrame)
956f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
957f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    void* fp = self->curFrame;
958f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int catchAddr = -1;
959f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
960f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(!dvmCheckException(self));
961f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
962f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (true) {
963f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        StackSaveArea* saveArea = SAVEAREA_FROM_FP(fp);
964f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        catchAddr = findCatchInMethod(self, saveArea->method, relPc,
965f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        exception->clazz);
966f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (catchAddr >= 0)
967f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
968f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
969f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
970f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Normally we'd check for ACC_SYNCHRONIZED methods and unlock
971f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * them as we unroll.  Dalvik uses what amount to generated
972f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * "finally" blocks to take care of this for us.
973f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
974f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
975f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* output method profiling info */
976f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!scanOnly) {
977f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            TRACE_METHOD_UNROLL(self, saveArea->method);
978f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
979f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
980f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
981f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Move up one frame.  If the next thing up is a break frame,
982f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * break out now so we're left unrolled to the last method frame.
983f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We need to point there so we can roll up the JNI local refs
984f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * if this was a native method.
985f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
986f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(saveArea->prevFrame != NULL);
987fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro        if (dvmIsBreakFrame((u4*)saveArea->prevFrame)) {
988f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!scanOnly)
989f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;      // bail with catchAddr == -1
990f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
991f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
992f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * We're scanning for the debugger.  It needs to know if this
993f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * exception is going to be caught or not, and we need to figure
994f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * out if it will be caught *ever* not just between the current
995f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * position and the next break frame.  We can't tell what native
996f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * code is going to do, so we assume it never catches exceptions.
997f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             *
998f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Start by finding an interpreted code frame.
999f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
1000f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            fp = saveArea->prevFrame;           // this is the break frame
1001f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            saveArea = SAVEAREA_FROM_FP(fp);
1002f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            fp = saveArea->prevFrame;           // this may be a good one
1003f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            while (fp != NULL) {
1004fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro                if (!dvmIsBreakFrame((u4*)fp)) {
1005f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    saveArea = SAVEAREA_FROM_FP(fp);
1006f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (!dvmIsNativeMethod(saveArea->method))
1007f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        break;
1008f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
1009f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1010f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                fp = SAVEAREA_FROM_FP(fp)->prevFrame;
1011f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1012f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (fp == NULL)
1013f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;      // bail with catchAddr == -1
1014f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1015f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
1016f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Now fp points to the "good" frame.  When the interp code
1017f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * invoked the native code, it saved a copy of its current PC
1018f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * into xtra.currentPc.  Pull it out of there.
1019f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
1020f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            relPc =
1021f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                saveArea->xtra.currentPc - SAVEAREA_FROM_FP(fp)->method->insns;
1022f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
1023f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            fp = saveArea->prevFrame;
1024f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1025f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* savedPc in was-current frame goes with method in now-current */
1026f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            relPc = saveArea->savedPc - SAVEAREA_FROM_FP(fp)->method->insns;
1027f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1028f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1029f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1030f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!scanOnly)
1031f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        self->curFrame = fp;
1032f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1033f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1034f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The class resolution in findCatchInMethod() could cause an exception.
1035f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Clear it to be safe.
1036f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1037f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    self->exception = NULL;
1038f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1039f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    *newFrame = fp;
1040f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return catchAddr;
1041f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1042f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1043f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1044f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We have to carry the exception's stack trace around, but in many cases
1045f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * it will never be examined.  It makes sense to keep it in a compact,
1046f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * VM-specific object, rather than an array of Objects with strings.
1047f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1048f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Pass in the thread whose stack we're interested in.  If "thread" is
1049f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * not self, the thread must be suspended.  This implies that the thread
1050f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * list lock is held, which means we can't allocate objects or we risk
1051f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * jamming the GC.  So, we allow this function to return different formats.
1052f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (This shouldn't be called directly -- see the inline functions in the
1053f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * header file.)
1054f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1055f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If "wantObject" is true, this returns a newly-allocated Object, which is
1056f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * presently an array of integers, but could become something else in the
1057f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * future.  If "wantObject" is false, return plain malloc data.
1058f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1059f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * NOTE: if we support class unloading, we will need to scan the class
1060f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * object references out of these arrays.
1061f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1062f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid* dvmFillInStackTraceInternal(Thread* thread, bool wantObject, int* pCount)
1063f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1064f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ArrayObject* stackData = NULL;
1065f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int* simpleData = NULL;
1066f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    void* fp;
1067f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    void* startFp;
1068f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int stackDepth;
1069f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int* intPtr;
1070f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1071f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pCount != NULL)
1072f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *pCount = 0;
1073f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fp = thread->curFrame;
1074f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1075f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(thread == dvmThreadSelf() || dvmIsSuspended(thread));
1076f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1077f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1078f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We're looking at a stack frame for code running below a Throwable
1079f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * constructor.  We want to remove the Throwable methods and the
1080f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * superclass initializations so the user doesn't see them when they
1081f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * read the stack dump.
1082f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
1083f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * TODO: this just scrapes off the top layers of Throwable.  Might not do
1084f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the right thing if we create an exception object or cause a VM
1085f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * exception while in a Throwable method.
1086f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1087f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (fp != NULL) {
1088f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const StackSaveArea* saveArea = SAVEAREA_FROM_FP(fp);
1089f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const Method* method = saveArea->method;
1090f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1091fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro        if (dvmIsBreakFrame((u4*)fp))
1092f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
109332bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein        if (!dvmInstanceof(method->clazz, gDvm.exThrowable))
1094f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1095f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //LOGD("EXCEP: ignoring %s.%s\n",
1096f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //         method->clazz->descriptor, method->name);
1097f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fp = saveArea->prevFrame;
1098f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1099f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    startFp = fp;
1100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Compute the stack depth.
1103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    stackDepth = 0;
1105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (fp != NULL) {
1106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const StackSaveArea* saveArea = SAVEAREA_FROM_FP(fp);
1107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1108fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro        if (!dvmIsBreakFrame((u4*)fp))
1109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            stackDepth++;
1110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(fp != saveArea->prevFrame);
1112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fp = saveArea->prevFrame;
1113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //LOGD("EXCEP: stack depth is %d\n", stackDepth);
1115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!stackDepth)
1117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
1118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We need to store a pointer to the Method and the program counter.
1121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We have 4-byte pointers, so we use '[I'.
1122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (wantObject) {
1124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(sizeof(Method*) == 4);
1125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        stackData = dvmAllocPrimitiveArray('I', stackDepth*2, ALLOC_DEFAULT);
1126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (stackData == NULL) {
1127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(dvmCheckException(dvmThreadSelf()));
1128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
1129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        intPtr = (int*) stackData->contents;
1131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
1132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* array of ints; first entry is stack depth */
1133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(sizeof(Method*) == sizeof(int));
1134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        simpleData = (int*) malloc(sizeof(int) * stackDepth*2);
1135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (simpleData == NULL)
1136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
1137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(pCount != NULL);
1139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        intPtr = simpleData;
1140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pCount != NULL)
1142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *pCount = stackDepth;
1143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fp = startFp;
1145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (fp != NULL) {
1146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const StackSaveArea* saveArea = SAVEAREA_FROM_FP(fp);
1147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const Method* method = saveArea->method;
1148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1149fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro        if (!dvmIsBreakFrame((u4*)fp)) {
1150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //LOGD("EXCEP keeping %s.%s\n", method->clazz->descriptor,
1151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //         method->name);
1152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *intPtr++ = (int) method;
1154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (dvmIsNativeMethod(method)) {
1155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                *intPtr++ = 0;      /* no saved PC for native methods */
1156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
1157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                assert(saveArea->xtra.currentPc >= method->insns &&
1158de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro                        saveArea->xtra.currentPc <
1159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        method->insns + dvmGetMethodInsnsSize(method));
1160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                *intPtr++ = (int) (saveArea->xtra.currentPc - method->insns);
1161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            stackDepth--;       // for verification
1164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(fp != saveArea->prevFrame);
1167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fp = saveArea->prevFrame;
1168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(stackDepth == 0);
1170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
1172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (wantObject) {
1173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmReleaseTrackedAlloc((Object*) stackData, dvmThreadSelf());
1174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return stackData;
1175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
1176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return simpleData;
1177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Given an Object previously created by dvmFillInStackTrace(), use the
1183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * contents of the saved stack trace to generate an array of
1184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * java/lang/StackTraceElement objects.
1185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The returned array is not added to the "local refs" list.
1187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectArrayObject* dvmGetStackTrace(const Object* ostackData)
1189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const ArrayObject* stackData = (const ArrayObject*) ostackData;
1191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const int* intVals;
1192e3c01dac83e6eea7f82fe81ed89cfbdd9791dbc9Carl Shapiro    int stackSize;
1193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    stackSize = stackData->length / 2;
1195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    intVals = (const int*) stackData->contents;
1196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return dvmGetStackTraceRaw(intVals, stackSize);
1197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Generate an array of StackTraceElement objects from the raw integer
1201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * data encoded by dvmFillInStackTrace().
1202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "intVals" points to the first {method,pc} pair.
1204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The returned array is not added to the "local refs" list.
1206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectArrayObject* dvmGetStackTraceRaw(const int* intVals, int stackDepth)
1208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ArrayObject* steArray = NULL;
1210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
1211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* init this if we haven't yet */
1213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!dvmIsClassInitialized(gDvm.classJavaLangStackTraceElement))
1214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmInitClass(gDvm.classJavaLangStackTraceElement);
1215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* allocate a StackTraceElement array */
1217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    steArray = dvmAllocArray(gDvm.classJavaLangStackTraceElementArray,
1218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    stackDepth, kObjectArrayRefWidth, ALLOC_DEFAULT);
1219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (steArray == NULL)
1220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
1221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Allocate and initialize a StackTraceElement for each stack frame.
1224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We use the standard constructor to configure the object.
1225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < stackDepth; i++) {
1227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Object* ste;
1228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Method* meth;
1229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        StringObject* className;
1230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        StringObject* methodName;
1231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        StringObject* fileName;
1232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int lineNumber, pc;
1233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const char* sourceFile;
1234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char* dotName;
1235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ste = dvmAllocObject(gDvm.classJavaLangStackTraceElement,ALLOC_DEFAULT);
1237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (ste == NULL)
1238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
1239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        meth = (Method*) *intVals++;
1241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pc = *intVals++;
1242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pc == -1)      // broken top frame?
1244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            lineNumber = 0;
1245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        else
1246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            lineNumber = dvmLineNumFromPC(meth, pc);
1247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
12485016966b91f1bc36b2bd52ec13ecfd8de1c68209Elliott Hughes        dotName = dvmHumanReadableDescriptor(meth->clazz->descriptor);
124981f3ebe03cd33c9003641084bece0604ee68bf88Barry Hayes        className = dvmCreateStringFromCstr(dotName);
1250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        free(dotName);
1251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
125281f3ebe03cd33c9003641084bece0604ee68bf88Barry Hayes        methodName = dvmCreateStringFromCstr(meth->name);
1253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sourceFile = dvmGetMethodSourceFile(meth);
1254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (sourceFile != NULL)
125581f3ebe03cd33c9003641084bece0604ee68bf88Barry Hayes            fileName = dvmCreateStringFromCstr(sourceFile);
1256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        else
1257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            fileName = NULL;
1258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
1260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Invoke:
1261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *  public StackTraceElement(String declaringClass, String methodName,
1262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *      String fileName, int lineNumber)
1263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * (where lineNumber==-2 means "native")
1264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        JValue unused;
1266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmCallMethod(dvmThreadSelf(), gDvm.methJavaLangStackTraceElement_init,
1267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ste, &unused, className, methodName, fileName, lineNumber);
1268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmReleaseTrackedAlloc(ste, NULL);
1270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmReleaseTrackedAlloc((Object*) className, NULL);
1271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmReleaseTrackedAlloc((Object*) methodName, NULL);
1272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmReleaseTrackedAlloc((Object*) fileName, NULL);
1273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (dvmCheckException(dvmThreadSelf()))
1275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
1276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1277364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes        dvmSetObjectArrayElement(steArray, i, ste);
1278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
1281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmReleaseTrackedAlloc((Object*) steArray, NULL);
1282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return steArray;
1283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump the contents of a raw stack trace to the log.
1287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmLogRawStackTrace(const int* intVals, int stackDepth)
1289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
1291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Run through the array of stack frame data.
1294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < stackDepth; i++) {
1296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Method* meth;
1297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int lineNumber, pc;
1298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const char* sourceFile;
1299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char* dotName;
1300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        meth = (Method*) *intVals++;
1302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pc = *intVals++;
1303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pc == -1)      // broken top frame?
1305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            lineNumber = 0;
1306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        else
1307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            lineNumber = dvmLineNumFromPC(meth, pc);
1308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // probably don't need to do this, but it looks nicer
13105016966b91f1bc36b2bd52ec13ecfd8de1c68209Elliott Hughes        dotName = dvmHumanReadableDescriptor(meth->clazz->descriptor);
1311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (dvmIsNativeMethod(meth)) {
1313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGI("\tat %s.%s(Native Method)\n", dotName, meth->name);
1314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
1315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGI("\tat %s.%s(%s:%d)\n",
1316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dotName, meth->name, dvmGetMethodSourceFile(meth),
1317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmLineNumFromPC(meth, pc));
1318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        free(dotName);
1321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sourceFile = dvmGetMethodSourceFile(meth);
1323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
13278552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden * Get the message string.  We'd like to just grab the field out of
13288552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden * Throwable, but the getMessage() function can be overridden by the
13298552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden * sub-class.
13308552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden *
13318552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden * Returns the message string object, or NULL if it wasn't set or
13328552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden * we encountered a failure trying to retrieve it.  The string will
13338552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden * be added to the tracked references table.
13348552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden */
13358552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFaddenstatic StringObject* getExceptionMessage(Object* exception)
13368552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden{
13378552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden    Thread* self = dvmThreadSelf();
13388552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden    Method* getMessageMethod;
13398552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden    StringObject* messageStr = NULL;
13408552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden
13418552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden    assert(exception == self->exception);
134250cab51bb381c5da01adfd61954ddca37607f51eAndy McFadden    dvmAddTrackedAlloc(exception, self);
13438552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden    self->exception = NULL;
13448552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden
13458552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden    getMessageMethod = dvmFindVirtualMethodHierByDescriptor(exception->clazz,
13468552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden            "getMessage", "()Ljava/lang/String;");
13478552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden    if (getMessageMethod != NULL) {
13488552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden        /* could be in NATIVE mode from CheckJNI, so switch state */
13498552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden        ThreadStatus oldStatus = dvmChangeStatus(self, THREAD_RUNNING);
13508552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden        JValue result;
13518552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden
13528552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden        dvmCallMethod(self, getMessageMethod, exception, &result);
13538552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden        messageStr = (StringObject*) result.l;
1354bd74b4b51f16e200854e41bbbe5ee6afb3af4cffAndy McFadden        if (messageStr != NULL)
1355bd74b4b51f16e200854e41bbbe5ee6afb3af4cffAndy McFadden            dvmAddTrackedAlloc((Object*) messageStr, self);
13568552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden
13578552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden        dvmChangeStatus(self, oldStatus);
13588552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden    } else {
13598552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden        LOGW("WARNING: could not find getMessage in %s\n",
13608552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden            exception->clazz->descriptor);
13618552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden    }
13628552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden
13638552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden    if (self->exception != NULL) {
13648552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden        LOGW("NOTE: exception thrown while retrieving exception message: %s\n",
13658552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden            self->exception->clazz->descriptor);
13668552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden    }
13678552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden
13688552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden    self->exception = exception;
136950cab51bb381c5da01adfd61954ddca37607f51eAndy McFadden    dvmReleaseTrackedAlloc(exception, self);
13708552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden    return messageStr;
13718552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden}
13728552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden
13738552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden/*
1374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Print the direct stack trace of the given exception to the log.
1375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void logStackTraceOf(Object* exception)
1377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const ArrayObject* stackData;
1379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    StringObject* messageStr;
1380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int stackSize;
1381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const int* intVals;
1382de952db74f54108630a3dd24af0b38e583b62ed3Andy McFadden    char* className;
1383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
13845016966b91f1bc36b2bd52ec13ecfd8de1c68209Elliott Hughes    className = dvmHumanReadableDescriptor(exception->clazz->descriptor);
13858552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden    messageStr = getExceptionMessage(exception);
1386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (messageStr != NULL) {
1387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char* cp = dvmCreateCstrFromString(messageStr);
13888552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden        dvmReleaseTrackedAlloc((Object*) messageStr, dvmThreadSelf());
13898552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden        messageStr = NULL;
13908552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden
1391de952db74f54108630a3dd24af0b38e583b62ed3Andy McFadden        LOGI("%s: %s\n", className, cp);
1392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        free(cp);
1393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
1394de952db74f54108630a3dd24af0b38e583b62ed3Andy McFadden        LOGI("%s:\n", className);
1395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1396de952db74f54108630a3dd24af0b38e583b62ed3Andy McFadden    free(className);
1397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1398de952db74f54108630a3dd24af0b38e583b62ed3Andy McFadden    /*
1399de952db74f54108630a3dd24af0b38e583b62ed3Andy McFadden     * This relies on the stackState field, which contains the "raw"
1400de952db74f54108630a3dd24af0b38e583b62ed3Andy McFadden     * form of the stack.  The Throwable class may clear this field
1401de952db74f54108630a3dd24af0b38e583b62ed3Andy McFadden     * after it generates the "cooked" form, in which case we'll have
1402de952db74f54108630a3dd24af0b38e583b62ed3Andy McFadden     * nothing to show.
1403de952db74f54108630a3dd24af0b38e583b62ed3Andy McFadden     */
1404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    stackData = (const ArrayObject*) dvmGetFieldObject(exception,
1405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    gDvm.offJavaLangThrowable_stackState);
1406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (stackData == NULL) {
1407de952db74f54108630a3dd24af0b38e583b62ed3Andy McFadden        LOGI("  (raw stack trace not found)\n");
1408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
1409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    stackSize = stackData->length / 2;
1412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    intVals = (const int*) stackData->contents;
1413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLogRawStackTrace(intVals, stackSize);
1415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Print the stack trace of the current thread's exception, as well as
1419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the stack traces of any chained exceptions, to the log. We extract
1420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the stored stack trace and process it internally instead of calling
1421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * interpreted code.
1422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmLogExceptionStackTrace(void)
1424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object* exception = dvmThreadSelf()->exception;
1426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object* cause;
1427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (exception == NULL) {
1429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("tried to log a null exception?\n");
1430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
1431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (;;) {
1434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        logStackTraceOf(exception);
1435686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden        cause = dvmGetExceptionCause(exception);
1436686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden        if (cause == NULL) {
1437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGI("Caused by:\n");
1440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        exception = cause;
1441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
14430016024cdd2bdeef3b98c92f7a8f40a2bc1ff42dElliott Hughes
1444d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowAbstractMethodError(const char* msg) {
1445d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein    dvmThrowException("Ljava/lang/AbstractMethodError;", msg);
1446d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1447d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
1448d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowArithmeticException(const char* msg) {
14496d167a4b02f310700a55fc9a24fccce999e0fdf2Dan Bornstein    dvmThrowExceptionByClass(gDvm.exArithmeticException, msg);
1450d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1451d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
145274501e600dcb5634aa26aee0a3f57f2b45b213f2Dan Bornsteinvoid dvmThrowArrayIndexOutOfBoundsException(int index, int length)
145374501e600dcb5634aa26aee0a3f57f2b45b213f2Dan Bornstein{
14549b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein    dvmThrowExceptionFmtByClass(gDvm.exArrayIndexOutOfBoundsException,
14559b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein        "length=%d; index=%d", length, index);
145674501e600dcb5634aa26aee0a3f57f2b45b213f2Dan Bornstein}
145774501e600dcb5634aa26aee0a3f57f2b45b213f2Dan Bornstein
14586d167a4b02f310700a55fc9a24fccce999e0fdf2Dan Bornstein/*
14596d167a4b02f310700a55fc9a24fccce999e0fdf2Dan Bornstein * Throw the indicated exception, with a message based on a format
14606d167a4b02f310700a55fc9a24fccce999e0fdf2Dan Bornstein * in which "%s" is used exactly twice, first for a received class and
14616d167a4b02f310700a55fc9a24fccce999e0fdf2Dan Bornstein * second for the expected class.
14626d167a4b02f310700a55fc9a24fccce999e0fdf2Dan Bornstein */
14636d167a4b02f310700a55fc9a24fccce999e0fdf2Dan Bornsteinstatic void throwTypeError(ClassObject* exceptionClass, const char* fmt,
146463644657f74e0a5d05f2c5fb56a18872e7ac7427Elliott Hughes    ClassObject* actual, ClassObject* desired)
1465c560e30f68265068bed9eadf174d1e76288d2952Elliott Hughes{
14665016966b91f1bc36b2bd52ec13ecfd8de1c68209Elliott Hughes    char* actualClassName = dvmHumanReadableDescriptor(actual->descriptor);
14675016966b91f1bc36b2bd52ec13ecfd8de1c68209Elliott Hughes    char* desiredClassName = dvmHumanReadableDescriptor(desired->descriptor);
14686d167a4b02f310700a55fc9a24fccce999e0fdf2Dan Bornstein    dvmThrowExceptionFmtByClass(exceptionClass, fmt,
1469c560e30f68265068bed9eadf174d1e76288d2952Elliott Hughes        actualClassName, desiredClassName);
1470c560e30f68265068bed9eadf174d1e76288d2952Elliott Hughes    free(desiredClassName);
1471c560e30f68265068bed9eadf174d1e76288d2952Elliott Hughes    free(actualClassName);
1472c560e30f68265068bed9eadf174d1e76288d2952Elliott Hughes}
147363644657f74e0a5d05f2c5fb56a18872e7ac7427Elliott Hughes
147463644657f74e0a5d05f2c5fb56a18872e7ac7427Elliott Hughesvoid dvmThrowArrayStoreException(ClassObject* actual, ClassObject* desired)
147563644657f74e0a5d05f2c5fb56a18872e7ac7427Elliott Hughes{
14766d167a4b02f310700a55fc9a24fccce999e0fdf2Dan Bornstein    throwTypeError(gDvm.exArrayStoreException,
147763644657f74e0a5d05f2c5fb56a18872e7ac7427Elliott Hughes        "%s cannot be stored in an array of type %s",
147863644657f74e0a5d05f2c5fb56a18872e7ac7427Elliott Hughes        actual, desired);
147963644657f74e0a5d05f2c5fb56a18872e7ac7427Elliott Hughes}
148063644657f74e0a5d05f2c5fb56a18872e7ac7427Elliott Hughes
148163644657f74e0a5d05f2c5fb56a18872e7ac7427Elliott Hughesvoid dvmThrowClassCastException(ClassObject* actual, ClassObject* desired)
148263644657f74e0a5d05f2c5fb56a18872e7ac7427Elliott Hughes{
14836d167a4b02f310700a55fc9a24fccce999e0fdf2Dan Bornstein    throwTypeError(gDvm.exClassCastException,
148463644657f74e0a5d05f2c5fb56a18872e7ac7427Elliott Hughes        "%s cannot be cast to %s", actual, desired);
148563644657f74e0a5d05f2c5fb56a18872e7ac7427Elliott Hughes}
1486d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
148770b00abc45d7d04342a96a03749f993028b060f7Dan Bornsteinvoid dvmThrowClassCircularityError(const char* descriptor) {
148870b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein    dvmThrowExceptionWithClassMessage("Ljava/lang/ClassCircularityError;",
148970b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein            descriptor);
149070b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein}
149170b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein
149270b00abc45d7d04342a96a03749f993028b060f7Dan Bornsteinvoid dvmThrowClassFormatError(const char* msg) {
14932c8e25b2010d1bba4dca0148691bc6e1a4ee7616Dan Bornstein    dvmThrowExceptionByClass(gDvm.exClassFormatError, msg);
149470b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein}
149570b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein
14969b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornsteinvoid dvmThrowClassNotFoundException(const char* name) {
14979b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein    // TODO: Should the name be converted into human-readable form?
14989b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein    dvmThrowExceptionByClass(gDvm.exClassNotFoundException, name);
14999b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein}
15009b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein
15019b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornsteinvoid dvmThrowChainedClassNotFoundException(const char* name, Object* cause) {
15029b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein    // TODO: Should the name be converted into human-readable form?
15039b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein    dvmThrowChainedExceptionByClass(gDvm.exClassNotFoundException, name,
15049b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein            cause);
15059b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein}
15069b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein
15079b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornsteinvoid dvmThrowExceptionInInitializerError(void)
15089b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein{
15099b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein    /*
15109b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein     * TODO: Do we want to wrap it if the original is an Error rather than
15119b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein     * an Exception?
15129b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein     *
15139b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein     * TODO: Should this just use dvmWrapException()?
15149b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein     */
15159b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein
15169b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein    if (gDvm.exExceptionInInitializerError == NULL) {
15179b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein        /*
15189b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein         * ExceptionInInitializerError isn't itself initialized. This
15199b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein         * can happen very early during VM startup if there is a
15209b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein         * problem with one of the corest-of-the-core classes, and it
15219b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein         * can possibly happen during a dexopt run. Rather than do
15229b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein         * anything fancier, we just abort here with a blatant
15239b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein         * message.
15249b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein         */
15259b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein        LOGE("Fatal error during early class initialization:\n");
15269b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein        dvmLogExceptionStackTrace();
15279b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein        dvmAbort();
15289b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein    }
15299b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein
15309b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein    Thread* self = dvmThreadSelf();
15319b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein    Object* exception = dvmGetException(self);
15329b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein
15339b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein    dvmAddTrackedAlloc(exception, self);
15349b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein    dvmClearException(self);
15359b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein
15369b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein    dvmThrowChainedExceptionByClass(gDvm.exExceptionInInitializerError,
15379b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein            NULL, exception);
15389b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein    dvmReleaseTrackedAlloc(exception, self);
1539d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1540d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
1541d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowFileNotFoundException(const char* msg) {
15422c8e25b2010d1bba4dca0148691bc6e1a4ee7616Dan Bornstein    dvmThrowExceptionByClass(gDvm.exFileNotFoundException, msg);
1543d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1544d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
1545d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowIOException(const char* msg) {
15462c8e25b2010d1bba4dca0148691bc6e1a4ee7616Dan Bornstein    dvmThrowExceptionByClass(gDvm.exIOException, msg);
1547d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1548d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
1549d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowIllegalAccessException(const char* msg) {
15509b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein    dvmThrowExceptionByClass(gDvm.exIllegalAccessException, msg);
1551d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1552d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
1553d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowIllegalAccessError(const char* msg) {
1554d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein    dvmThrowException("Ljava/lang/IllegalAccessError;", msg);
1555d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1556d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
1557d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowIllegalArgumentException(const char* msg) {
1558d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein    dvmThrowException("Ljava/lang/IllegalArgumentException;", msg);
1559d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1560d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
1561d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowIllegalMonitorStateException(const char* msg) {
1562d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein    dvmThrowException("Ljava/lang/IllegalMonitorStateException;", msg);
1563d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1564d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
1565d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowIllegalStateException(const char* msg) {
1566d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein    dvmThrowException("Ljava/lang/IllegalStateException;", msg);
1567d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1568d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
1569d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowIllegalThreadStateException(const char* msg) {
1570d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein    dvmThrowException("Ljava/lang/IllegalThreadStateException;", msg);
1571d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1572d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
157370b00abc45d7d04342a96a03749f993028b060f7Dan Bornsteinvoid dvmThrowIncompatibleClassChangeError(const char* msg) {
157470b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein    dvmThrowException("Ljava/lang/IncompatibleClassChangeError;", msg);
157570b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein}
157670b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein
157770b00abc45d7d04342a96a03749f993028b060f7Dan Bornsteinvoid dvmThrowIncompatibleClassChangeErrorWithClassMessage(
157870b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein        const char* descriptor)
157970b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein{
158070b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein    dvmThrowExceptionWithClassMessage(
158170b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein            "Ljava/lang/IncompatibleClassChangeError;", descriptor);
158270b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein}
158370b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein
1584d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowInternalError(const char* msg) {
1585d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein    dvmThrowException("Ljava/lang/InternalError;", msg);
1586d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1587d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
1588d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowInterruptedException(const char* msg) {
15899b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein    dvmThrowExceptionByClass(gDvm.exInterruptedException, msg);
1590d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1591d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
159270b00abc45d7d04342a96a03749f993028b060f7Dan Bornsteinvoid dvmThrowLinkageError(const char* msg) {
159370b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein    dvmThrowException("Ljava/lang/LinkageError;", msg);
159470b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein}
159570b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein
15962c8e25b2010d1bba4dca0148691bc6e1a4ee7616Dan Bornsteinvoid dvmThrowNegativeArraySizeException(s4 size) {
15972c8e25b2010d1bba4dca0148691bc6e1a4ee7616Dan Bornstein    dvmThrowExceptionFmtByClass(gDvm.exNegativeArraySizeException, "%d", size);
1598d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1599d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
1600d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowNoClassDefFoundError(const char* descriptor) {
1601d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein    dvmThrowExceptionWithClassMessage("Ljava/lang/NoClassDefFoundError;",
1602d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein            descriptor);
1603d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1604d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
1605d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowNoSuchFieldError(const char* msg) {
1606d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein    dvmThrowException("Ljava/lang/NoSuchFieldError;", msg);
1607d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1608d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
1609d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowNoSuchFieldException(const char* msg) {
16109b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein    dvmThrowExceptionByClass(gDvm.exNoSuchFieldException, msg);
1611d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1612d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
1613d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowNoSuchMethodError(const char* msg) {
1614d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein    dvmThrowException("Ljava/lang/NoSuchMethodError;", msg);
1615d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1616d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
1617d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowNullPointerException(const char* msg) {
16182c8e25b2010d1bba4dca0148691bc6e1a4ee7616Dan Bornstein    dvmThrowExceptionByClass(gDvm.exNullPointerException, msg);
1619d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1620d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
1621d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowOutOfMemoryError(const char* msg) {
1622d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein    dvmThrowException("Ljava/lang/OutOfMemoryError;", msg);
1623d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1624d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
1625d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowRuntimeException(const char* msg) {
162632bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein    dvmThrowExceptionByClass(gDvm.exRuntimeException, msg);
1627d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1628d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
162974501e600dcb5634aa26aee0a3f57f2b45b213f2Dan Bornsteinvoid dvmThrowStaleDexCacheError(const char* msg) {
16309b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein    dvmThrowExceptionByClass(gDvm.exStaleDexCacheError, msg);
163174501e600dcb5634aa26aee0a3f57f2b45b213f2Dan Bornstein}
163274501e600dcb5634aa26aee0a3f57f2b45b213f2Dan Bornstein
16337a86c44bde10b37d8df17d0613072c4ef134189cDan Bornsteinvoid dvmThrowStringIndexOutOfBoundsExceptionWithIndex(jsize stringLength,
16347a86c44bde10b37d8df17d0613072c4ef134189cDan Bornstein        jsize requestIndex) {
16357a86c44bde10b37d8df17d0613072c4ef134189cDan Bornstein    dvmThrowExceptionFmtByClass(gDvm.exStringIndexOutOfBoundsException,
163639f8af436c68c5ddfaf79f6f0372f535e2a52651Dan Bornstein            "length=%d; index=%d", stringLength, requestIndex);
16377a86c44bde10b37d8df17d0613072c4ef134189cDan Bornstein}
16387a86c44bde10b37d8df17d0613072c4ef134189cDan Bornstein
16397a86c44bde10b37d8df17d0613072c4ef134189cDan Bornsteinvoid dvmThrowStringIndexOutOfBoundsExceptionWithRegion(jsize stringLength,
16407a86c44bde10b37d8df17d0613072c4ef134189cDan Bornstein        jsize requestStart, jsize requestLength) {
16417a86c44bde10b37d8df17d0613072c4ef134189cDan Bornstein    dvmThrowExceptionFmtByClass(gDvm.exStringIndexOutOfBoundsException,
16427a86c44bde10b37d8df17d0613072c4ef134189cDan Bornstein            "length=%d; regionStart=%d regionLength=%d",
16437a86c44bde10b37d8df17d0613072c4ef134189cDan Bornstein            stringLength, requestStart, requestLength);
1644d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1645d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
164670b00abc45d7d04342a96a03749f993028b060f7Dan Bornsteinvoid dvmThrowUnsatisfiedLinkError(const char* msg) {
164770b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein    dvmThrowException("Ljava/lang/UnsatisfiedLinkError;", msg);
164870b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein}
164970b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein
1650d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowUnsupportedOperationException(const char* msg) {
16517a86c44bde10b37d8df17d0613072c4ef134189cDan Bornstein    dvmThrowExceptionByClass(gDvm.exUnsupportedOperationException, msg);
1652d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
165370b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein
165470b00abc45d7d04342a96a03749f993028b060f7Dan Bornsteinvoid dvmThrowVirtualMachineError(const char* msg) {
16557a86c44bde10b37d8df17d0613072c4ef134189cDan Bornstein    dvmThrowExceptionByClass(gDvm.exVirtualMachineError, msg);
165670b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein}
1657