Exception.cpp revision 74501e600dcb5634aa26aee0a3f57f2b45b213f2
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/*
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Cache pointers to some of the exception classes we use locally.
105686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden *
106686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden * Note this is NOT called during dexopt optimization.  Some of the fields
107686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden * are initialized by the verifier (dvmVerifyCodeFlow).
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmExceptionStartup(void)
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.classJavaLangThrowable =
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmFindSystemClassNoInit("Ljava/lang/Throwable;");
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.classJavaLangRuntimeException =
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmFindSystemClassNoInit("Ljava/lang/RuntimeException;");
1154fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden    gDvm.classJavaLangStackOverflowError =
1164fbba1f95b3e27bdc5f5572bb0420b5f928aa54eAndy McFadden        dvmFindSystemClassNoInit("Ljava/lang/StackOverflowError;");
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.classJavaLangError =
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmFindSystemClassNoInit("Ljava/lang/Error;");
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.classJavaLangStackTraceElement =
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmFindSystemClassNoInit("Ljava/lang/StackTraceElement;");
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.classJavaLangStackTraceElementArray =
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmFindArrayClass("[Ljava/lang/StackTraceElement;", NULL);
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.classJavaLangThrowable == NULL ||
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        gDvm.classJavaLangStackTraceElement == NULL ||
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        gDvm.classJavaLangStackTraceElementArray == NULL)
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGE("Could not find one or more essential exception classes\n");
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Find the constructor.  Note that, unlike other saved method lookups,
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * we're using a Method* instead of a vtable offset.  This is because
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * constructors don't have vtable offsets.  (Also, since we're creating
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the object in question, it's impossible for anyone to sub-class it.)
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Method* meth;
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    meth = dvmFindDirectMethodByDescriptor(gDvm.classJavaLangStackTraceElement,
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        "<init>", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V");
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (meth == NULL) {
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGE("Unable to find constructor for StackTraceElement\n");
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.methJavaLangStackTraceElement_init = meth;
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* grab an offset for the stackData field */
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.offJavaLangThrowable_stackState =
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmFindFieldOffset(gDvm.classJavaLangThrowable,
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "stackState", "Ljava/lang/Object;");
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.offJavaLangThrowable_stackState < 0) {
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGE("Unable to find Throwable.stackState\n");
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* and one for the cause field, just 'cause */
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.offJavaLangThrowable_cause =
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmFindFieldOffset(gDvm.classJavaLangThrowable,
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "cause", "Ljava/lang/Throwable;");
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.offJavaLangThrowable_cause < 0) {
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGE("Unable to find Throwable.cause\n");
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Clean up.
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmExceptionShutdown(void)
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // nothing to do
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1770171812e59e2520a4345b9bbadd4f7afa0a1de16Andy McFadden * Format the message into a small buffer and pass it along.
1780171812e59e2520a4345b9bbadd4f7afa0a1de16Andy McFadden */
1790171812e59e2520a4345b9bbadd4f7afa0a1de16Andy McFaddenvoid dvmThrowExceptionFmtV(const char* exceptionDescriptor, const char* fmt,
1800171812e59e2520a4345b9bbadd4f7afa0a1de16Andy McFadden    va_list args)
1810171812e59e2520a4345b9bbadd4f7afa0a1de16Andy McFadden{
1820171812e59e2520a4345b9bbadd4f7afa0a1de16Andy McFadden    char msgBuf[512];
1830171812e59e2520a4345b9bbadd4f7afa0a1de16Andy McFadden
1840171812e59e2520a4345b9bbadd4f7afa0a1de16Andy McFadden    vsnprintf(msgBuf, sizeof(msgBuf), fmt, args);
1850171812e59e2520a4345b9bbadd4f7afa0a1de16Andy McFadden    dvmThrowChainedException(exceptionDescriptor, msgBuf, NULL);
1860171812e59e2520a4345b9bbadd4f7afa0a1de16Andy McFadden}
1870171812e59e2520a4345b9bbadd4f7afa0a1de16Andy McFadden
1880171812e59e2520a4345b9bbadd4f7afa0a1de16Andy McFadden/*
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Create a Throwable and throw an exception in the current thread (where
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "throwing" just means "set the thread's exception pointer").
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "msg" and/or "cause" may be NULL.
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If we have a bad exception hierarchy -- something in Throwable.<init>
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * is missing -- then every attempt to throw an exception will result
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * in another exception.  Exceptions are generally allowed to "chain"
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to other exceptions, so it's hard to auto-detect this problem.  It can
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * only happen if the system classes are broken, so it's probably not
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * worth spending cycles to detect it.
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We do have one case to worry about: if the classpath is completely
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * wrong, we'll go into a death spin during startup because we can't find
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the initial class and then we can't find NoClassDefFoundError.  We have
204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to handle this case.
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * [Do we want to cache pointers to common exception classes?]
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmThrowChainedException(const char* exceptionDescriptor, const char* msg,
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object* cause)
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* excepClass;
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGV("THROW '%s' msg='%s' cause=%s\n",
214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        exceptionDescriptor, msg,
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        (cause != NULL) ? cause->clazz->descriptor : "(none)");
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.initializing) {
218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (++gDvm.initExceptionCount >= 2) {
219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGE("Too many exceptions during init (failed on '%s' '%s')\n",
220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                exceptionDescriptor, msg);
221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmAbort();
222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    excepClass = dvmFindSystemClass(exceptionDescriptor);
226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (excepClass == NULL) {
227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We couldn't find the exception class.  The attempt to find a
229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * nonexistent class should have raised an exception.  If no
230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * exception is currently raised, then we're pretty clearly unable
231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * to throw ANY sort of exception, and we need to pack it in.
232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * If we were able to throw the "class load failed" exception,
234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * stick with that.  Ideally we'd stuff the original exception
235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * into the "cause" field, but since we can't find it we can't
236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * do that.  The exception class name should be in the "message"
237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * field.
238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!dvmCheckException(dvmThreadSelf())) {
240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGE("FATAL: unable to throw exception (failed on '%s' '%s')\n",
241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                exceptionDescriptor, msg);
242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmAbort();
243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmThrowChainedExceptionByClass(excepClass, msg, cause);
248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Start/continue throwing process now that we have a class reference.
252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmThrowChainedExceptionByClass(ClassObject* excepClass, const char* msg,
254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object* cause)
255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Thread* self = dvmThreadSelf();
257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object* exception;
258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* make sure the exception is initialized */
260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!dvmIsClassInitialized(excepClass) && !dvmInitClass(excepClass)) {
261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGE("ERROR: unable to initialize exception class '%s'\n",
262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            excepClass->descriptor);
263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (strcmp(excepClass->descriptor, "Ljava/lang/InternalError;") == 0)
264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmAbort();
265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmThrowChainedException("Ljava/lang/InternalError;",
266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "failed to init original exception class", cause);
267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    exception = dvmAllocObject(excepClass, ALLOC_DEFAULT);
271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (exception == NULL) {
272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We're in a lot of trouble.  We might be in the process of
274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * throwing an out-of-memory exception, in which case the
275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * pre-allocated object will have been thrown when our object alloc
276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * failed.  So long as there's an exception raised, return and
277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * allow the system to try to recover.  If not, something is broken
278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * and we need to bail out.
279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (dvmCheckException(self))
281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGE("FATAL: unable to allocate exception '%s' '%s'\n",
283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            excepClass->descriptor, msg != NULL ? msg : "(no msg)");
284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmAbort();
285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Init the exception.
289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.optimizing) {
291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* need the exception object, but can't invoke interpreted code */
292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGV("Skipping init of exception %s '%s'\n",
293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            excepClass->descriptor, msg);
294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(excepClass == exception->clazz);
296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!initException(exception, msg, cause, self)) {
297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Whoops.  If we can't initialize the exception, we can't use
299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * it.  If there's an exception already set, the constructor
300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * probably threw an OutOfMemoryError.
301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!dvmCheckException(self)) {
303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /*
304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * We're required to throw something, so we just
305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * throw the pre-constructed internal error.
306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                self->exception = gDvm.internalErrorObj;
308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    self->exception = exception;
314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmReleaseTrackedAlloc(exception, self);
317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
3205016966b91f1bc36b2bd52ec13ecfd8de1c68209Elliott Hughes * Throw the named exception using the human-readable form of the class
321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * descriptor as the exception message, and with the specified cause.
322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmThrowChainedExceptionWithClassMessage(const char* exceptionDescriptor,
324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* messageDescriptor, Object* cause)
325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
3265016966b91f1bc36b2bd52ec13ecfd8de1c68209Elliott Hughes    char* message = dvmHumanReadableDescriptor(messageDescriptor);
327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmThrowChainedException(exceptionDescriptor, message, cause);
329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(message);
330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
333d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein * Like dvmThrowException, but take a class object instead of a name
334d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein * and turn the given message into the human-readable form for a descriptor.
335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmThrowExceptionByClassWithClassMessage(ClassObject* exceptionClass,
337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* messageDescriptor)
338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* message = dvmDescriptorToName(messageDescriptor);
340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmThrowExceptionByClass(exceptionClass, message);
342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(message);
343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
3464a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein * Find and return an exception constructor method that can take the
3474a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein * indicated parameters, or return NULL if no such constructor exists.
3484a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein */
3494a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornsteinstatic Method* findExceptionInitMethod(ClassObject* excepClass,
3504a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein    bool hasMessage, bool hasCause)
3514a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein{
3524a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein    if (hasMessage) {
3534a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein        Method* result;
3544a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein
3554a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein        if (hasCause) {
3564a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein            result = dvmFindDirectMethodByDescriptor(
3574a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein                    excepClass, "<init>",
3584a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein                    "(Ljava/lang/String;Ljava/lang/Throwable;)V");
3594a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein        } else {
3604a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein            result = dvmFindDirectMethodByDescriptor(
3614a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein                    excepClass, "<init>", "(Ljava/lang/String;)V");
3624a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein        }
3634a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein
3644a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein        if (result != NULL) {
3654a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein            return result;
3664a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein        }
3674a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein
3684a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein        if (hasCause) {
3694a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein            return dvmFindDirectMethodByDescriptor(
3704a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein                    excepClass, "<init>",
3714a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein                    "(Ljava/lang/Object;Ljava/lang/Throwable;)V");
3724a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein        } else {
3734a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein            return dvmFindDirectMethodByDescriptor(
3744a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein                    excepClass, "<init>", "(Ljava/lang/Object;)V");
3754a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein        }
3764a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein    } else if (hasCause) {
3774a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein        return dvmFindDirectMethodByDescriptor(
3784a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein                excepClass, "<init>", "(Ljava/lang/Throwable;)V");
3794a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein    } else {
3804a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein        return dvmFindDirectMethodByDescriptor(excepClass, "<init>", "()V");
3814a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein    }
3824a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein}
3834a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein
3844a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein/*
385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Initialize an exception with an appropriate constructor.
386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "exception" is the exception object to initialize.
388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Either or both of "msg" and "cause" may be null.
389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "self" is dvmThreadSelf(), passed in so we don't have to look it up again.
390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If the process of initializing the exception causes another
392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * exception (e.g., OutOfMemoryError) to be thrown, return an error
393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and leave self->exception intact.
394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool initException(Object* exception, const char* msg, Object* cause,
396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Thread* self)
397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    enum {
399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        kInitUnknown,
400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        kInitNoarg,
401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        kInitMsg,
402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        kInitMsgThrow,
403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        kInitThrow
404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } initKind = kInitUnknown;
405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Method* initMethod = NULL;
406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* excepClass = exception->clazz;
407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    StringObject* msgStr = NULL;
408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool result = false;
409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool needInitCause = false;
410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(self != NULL);
412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(self->exception == NULL);
413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* if we have a message, create a String */
415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (msg == NULL)
416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        msgStr = NULL;
417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    else {
41881f3ebe03cd33c9003641084bece0604ee68bf88Barry Hayes        msgStr = dvmCreateStringFromCstr(msg);
419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (msgStr == NULL) {
420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGW("Could not allocate message string \"%s\" while "
421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    "throwing internal exception (%s)\n",
422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    msg, excepClass->descriptor);
423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
427686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden    if (cause != NULL) {
428686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden        if (!dvmInstanceof(cause->clazz, gDvm.classJavaLangThrowable)) {
429686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden            LOGE("Tried to init exception with cause '%s'\n",
430686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden                cause->clazz->descriptor);
431686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden            dvmAbort();
432686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden        }
433686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden    }
434686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden
435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The Throwable class has four public constructors:
437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *  (1) Throwable()
438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *  (2) Throwable(String message)
439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *  (3) Throwable(String message, Throwable cause)  (added in 1.4)
440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *  (4) Throwable(Throwable cause)                  (added in 1.4)
441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The first two are part of the original design, and most exception
443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * classes should support them.  The third prototype was used by
444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * individual exceptions. e.g. ClassNotFoundException added it in 1.2.
445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The general "cause" mechanism was added in 1.4.  Some classes,
446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * such as IllegalArgumentException, initially supported the first
447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * two, but added the second two in a later release.
448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Exceptions may be picky about how their "cause" field is initialized.
450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * If you call ClassNotFoundException(String), it may choose to
451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * initialize its "cause" field to null.  Doing so prevents future
452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * calls to Throwable.initCause().
453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * So, if "cause" is not NULL, we need to look for a constructor that
455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * takes a throwable.  If we can't find one, we fall back on calling
456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * #1/#2 and making a separate call to initCause().  Passing a null ref
457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * for "message" into Throwable(String, Throwable) is allowed, but we
458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * prefer to use the Throwable-only version because it has different
459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * behavior.
460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * java.lang.TypeNotPresentException is a strange case -- it has #3 but
462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * not #2.  (Some might argue that the constructor is actually not #3,
463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * because it doesn't take the message string as an argument, but it
464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * has the same effect and we can work with it here.)
4654a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein     *
4664a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein     * java.lang.AssertionError is also a strange case -- it has a
4674a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein     * constructor that takes an Object, but not one that takes a String.
4684a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein     * There may be other cases like this, as well, so we generally look
4694a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein     * for an Object-taking constructor if we can't find one that takes
4704a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein     * a String.
471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (cause == NULL) {
473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (msgStr == NULL) {
4744a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein            initMethod = findExceptionInitMethod(excepClass, false, false);
475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            initKind = kInitNoarg;
476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
4774a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein            initMethod = findExceptionInitMethod(excepClass, true, false);
478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (initMethod != NULL) {
479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                initKind = kInitMsg;
480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* no #2, try #3 */
4824a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein                initMethod = findExceptionInitMethod(excepClass, true, true);
4834a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein                if (initMethod != NULL) {
484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    initKind = kInitMsgThrow;
4854a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein                }
486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (msgStr == NULL) {
4904a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein            initMethod = findExceptionInitMethod(excepClass, false, true);
491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (initMethod != NULL) {
492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                initKind = kInitThrow;
493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
4944a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein                initMethod = findExceptionInitMethod(excepClass, false, false);
495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                initKind = kInitNoarg;
496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                needInitCause = true;
497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
4994a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein            initMethod = findExceptionInitMethod(excepClass, true, true);
500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (initMethod != NULL) {
501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                initKind = kInitMsgThrow;
502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
5034a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein                initMethod = findExceptionInitMethod(excepClass, true, false);
504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                initKind = kInitMsg;
505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                needInitCause = true;
506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (initMethod == NULL) {
511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We can't find the desired constructor.  This can happen if a
513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * subclass of java/lang/Throwable doesn't define an expected
514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * constructor, e.g. it doesn't provide one that takes a string
515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * when a message has been provided.
516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("WARNING: exception class '%s' missing constructor "
518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "(msg='%s' kind=%d)\n",
519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            excepClass->descriptor, msg, initKind);
520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(strcmp(excepClass->descriptor,
521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                      "Ljava/lang/RuntimeException;") != 0);
522de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro        dvmThrowChainedException("Ljava/lang/RuntimeException;",
523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "re-throw on exception class missing constructor", NULL);
524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Call the constructor with the appropriate arguments.
529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    JValue unused;
531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    switch (initKind) {
532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kInitNoarg:
533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("+++ exc noarg (ic=%d)\n", needInitCause);
534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmCallMethod(self, initMethod, exception, &unused);
535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kInitMsg:
537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("+++ exc msg (ic=%d)\n", needInitCause);
538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmCallMethod(self, initMethod, exception, &unused, msgStr);
539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kInitThrow:
541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("+++ exc throw");
542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(!needInitCause);
543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmCallMethod(self, initMethod, exception, &unused, cause);
544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kInitMsgThrow:
546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("+++ exc msg+throw");
547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(!needInitCause);
548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmCallMethod(self, initMethod, exception, &unused, msgStr, cause);
549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    default:
551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(false);
552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * It's possible the constructor has thrown an exception.  If so, we
557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * return an error and let our caller deal with it.
558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (self->exception != NULL) {
560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("Exception thrown (%s) while throwing internal exception (%s)\n",
561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            self->exception->clazz->descriptor, exception->clazz->descriptor);
562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * If this exception was caused by another exception, and we weren't
567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * able to find a cause-setting constructor, set the "cause" field
568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * with an explicit call.
569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (needInitCause) {
571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Method* initCause;
572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        initCause = dvmFindVirtualMethodHierByDescriptor(excepClass, "initCause",
573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "(Ljava/lang/Throwable;)Ljava/lang/Throwable;");
574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (initCause != NULL) {
575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmCallMethod(self, initCause, exception, &unused, cause);
576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (self->exception != NULL) {
577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* initCause() threw an exception; return an error and
578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * let the caller deal with it.
579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOGW("Exception thrown (%s) during initCause() "
581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        "of internal exception (%s)\n",
582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        self->exception->clazz->descriptor,
583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        exception->clazz->descriptor);
584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                goto bail;
585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGW("WARNING: couldn't find initCause in '%s'\n",
588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                excepClass->descriptor);
589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    result = true;
594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmReleaseTrackedAlloc((Object*) msgStr, self);     // NULL is ok
597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return result;
598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Clear the pending exception and the "initExceptionCount" counter.  This
603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * is used by the optimization and verification code, which has to run with
604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "initializing" set to avoid going into a death-spin if the "class not
605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * found" exception can't be found.
606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This can also be called when the VM is in a "normal" state, e.g. when
608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * verifying classes that couldn't be verified at optimization time.  The
609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * reset of initExceptionCount should be harmless in that case.
610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmClearOptException(Thread* self)
612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    self->exception = NULL;
614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.initExceptionCount = 0;
615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns "true" if this is a "checked" exception, i.e. it's a subclass
619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * of Throwable (assumed) but not a subclass of RuntimeException or Error.
620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmIsCheckedException(const Object* exception)
622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dvmInstanceof(exception->clazz, gDvm.classJavaLangError) ||
624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmInstanceof(exception->clazz, gDvm.classJavaLangRuntimeException))
625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return true;
629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Wrap the now-pending exception in a different exception.  This is useful
634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * for reflection stuff that wants to hand a checked exception back from a
635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * method that doesn't declare it.
636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If something fails, an (unchecked) exception related to that failure
638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * will be pending instead.
639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmWrapException(const char* newExcepStr)
641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Thread* self = dvmThreadSelf();
643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object* origExcep;
644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* iteClass;
645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    origExcep = dvmGetException(self);
647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmAddTrackedAlloc(origExcep, self);    // don't let the GC free it
648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmClearException(self);                // clear before class lookup
650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    iteClass = dvmFindSystemClass(newExcepStr);
651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (iteClass != NULL) {
652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Object* iteExcep;
653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Method* initMethod;
654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        iteExcep = dvmAllocObject(iteClass, ALLOC_DEFAULT);
656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (iteExcep != NULL) {
657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            initMethod = dvmFindDirectMethodByDescriptor(iteClass, "<init>",
658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            "(Ljava/lang/Throwable;)V");
659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (initMethod != NULL) {
660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                JValue unused;
661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmCallMethod(self, initMethod, iteExcep, &unused,
662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    origExcep);
663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* if <init> succeeded, replace the old exception */
665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (!dvmCheckException(self))
666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    dvmSetException(self, iteExcep);
667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmReleaseTrackedAlloc(iteExcep, NULL);
669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* if initMethod doesn't exist, or failed... */
671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!dvmCheckException(self))
672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmSetException(self, origExcep);
673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* leave OutOfMemoryError pending */
675f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
676f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* leave ClassNotFoundException pending */
678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
679f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(dvmCheckException(self));
681f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmReleaseTrackedAlloc(origExcep, self);
682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
683f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
685686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden * Get the "cause" field from an exception.
686686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden *
687686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden * The Throwable class initializes the "cause" field to "this" to
688686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden * differentiate between being initialized to null and never being
689686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden * initialized.  We check for that here and convert it to NULL.
690686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden */
691686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFaddenObject* dvmGetExceptionCause(const Object* exception)
692686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden{
693686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden    if (!dvmInstanceof(exception->clazz, gDvm.classJavaLangThrowable)) {
694686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden        LOGE("Tried to get cause from object of type '%s'\n",
695686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden            exception->clazz->descriptor);
696686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden        dvmAbort();
697686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden    }
698686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden    Object* cause =
699686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden        dvmGetFieldObject(exception, gDvm.offJavaLangThrowable_cause);
700686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden    if (cause == exception)
701686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden        return NULL;
702686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden    else
703686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden        return cause;
704686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden}
705686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden
706686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden/*
707f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Print the stack trace of the current exception on stderr.  This is called
708f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * from the JNI ExceptionDescribe call.
709f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
710f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * For consistency we just invoke the Throwable printStackTrace method,
711f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * which might be overridden in the exception object.
712f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Exceptions thrown during the course of printing the stack trace are
714f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ignored.
715f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
716f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmPrintExceptionStackTrace(void)
717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
718f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Thread* self = dvmThreadSelf();
719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object* exception;
720f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Method* printMethod;
721f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
722f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    exception = self->exception;
723f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (exception == NULL)
724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
725f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
72650cab51bb381c5da01adfd61954ddca37607f51eAndy McFadden    dvmAddTrackedAlloc(exception, self);
727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    self->exception = NULL;
728f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printMethod = dvmFindVirtualMethodHierByDescriptor(exception->clazz,
729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    "printStackTrace", "()V");
730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (printMethod != NULL) {
731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        JValue unused;
732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmCallMethod(self, printMethod, exception, &unused);
733f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
734f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("WARNING: could not find printStackTrace in %s\n",
735f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            exception->clazz->descriptor);
736f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
737f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
738f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (self->exception != NULL) {
73922680eee4aa012c839568d83a132b2b20ff39525Elliott Hughes        LOGW("NOTE: exception thrown while printing stack trace: %s\n",
740f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            self->exception->clazz->descriptor);
741f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
742f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    self->exception = exception;
74450cab51bb381c5da01adfd61954ddca37607f51eAndy McFadden    dvmReleaseTrackedAlloc(exception, self);
745f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
746f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
747f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
748f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Search the method's list of exceptions for a match.
749f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns the offset of the catch block on success, or -1 on failure.
751f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
752f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int findCatchInMethod(Thread* self, const Method* method, int relPc,
753f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* excepClass)
754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Need to clear the exception before entry.  Otherwise, dvmResolveClass
757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * might think somebody threw an exception while it was loading a class.
758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(!dvmCheckException(self));
760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(!dvmIsNativeMethod(method));
761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGVV("findCatchInMethod %s.%s excep=%s depth=%d\n",
763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        method->clazz->descriptor, method->name, excepClass->descriptor,
764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmComputeExactFrameDepth(self->curFrame));
765f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
766f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DvmDex* pDvmDex = method->clazz->pDvmDex;
767f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexCode* pCode = dvmGetMethodCode(method);
768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DexCatchIterator iterator;
769f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
770f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dexFindCatchHandler(&iterator, pCode, relPc)) {
771f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (;;) {
772f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            DexCatchHandler* handler = dexCatchIteratorNext(&iterator);
773f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
774f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (handler == NULL) {
775f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
776f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
777de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
778f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (handler->typeIdx == kDexNoIndex) {
779f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* catch-all */
780f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOGV("Match on catch-all block at 0x%02x in %s.%s for %s\n",
781f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        relPc, method->clazz->descriptor,
782f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        method->name, excepClass->descriptor);
783f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return handler->address;
784f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
786f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ClassObject* throwable =
787f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmDexGetResolvedClass(pDvmDex, handler->typeIdx);
788f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (throwable == NULL) {
789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /*
790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * TODO: this behaves badly if we run off the stack
791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * while trying to throw an exception.  The problem is
792f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * that, if we're in a class loaded by a class loader,
793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * the call to dvmResolveClass has to ask the class
794f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * loader for help resolving any previously-unresolved
795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * classes.  If this particular class loader hasn't
796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * resolved StackOverflowError, it will call into
797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * interpreted code, and blow up.
798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 *
799f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * We currently replace the previous exception with
800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * the StackOverflowError, which means they won't be
801f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * catching it *unless* they explicitly catch
802f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * StackOverflowError, in which case we'll be unable
803f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * to resolve the class referred to by the "catch"
804f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * block.
805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 *
806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * We end up getting a huge pile of warnings if we do
807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * a simple synthetic test, because this method gets
808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * called on every stack frame up the tree, and it
809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * fails every time.
810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 *
811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * This eventually bails out, effectively becoming an
812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * uncatchable exception, so other than the flurry of
813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * warnings it's not really a problem.  Still, we could
814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * probably handle this better.
815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                throwable = dvmResolveClass(method->clazz, handler->typeIdx,
817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    true);
818f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (throwable == NULL) {
819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    /*
820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     * We couldn't find the exception they wanted in
821f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     * our class files (or, perhaps, the stack blew up
822f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     * while we were querying a class loader). Cough
823f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     * up a warning, then move on to the next entry.
824f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     * Keep the exception status clear.
825f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     */
826f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LOGW("Could not resolve class ref'ed in exception "
827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            "catch list (class index %d, exception %s)\n",
828f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            handler->typeIdx,
829f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            (self->exception != NULL) ?
830f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            self->exception->clazz->descriptor : "(none)");
831f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    dvmClearException(self);
832f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    continue;
833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
834f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
835f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
836f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //LOGD("ADDR MATCH, check %s instanceof %s\n",
837f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //    excepClass->descriptor, pEntry->excepClass->descriptor);
838f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
839f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (dvmInstanceof(excepClass, throwable)) {
840f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOGV("Match on catch block at 0x%02x in %s.%s for %s\n",
841f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        relPc, method->clazz->descriptor,
842f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        method->name, excepClass->descriptor);
843f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return handler->address;
844f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
845f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
846f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
847f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGV("No matching catch block at 0x%02x in %s for %s\n",
849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        relPc, method->name, excepClass->descriptor);
850f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return -1;
851f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
852f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
853f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Find a matching "catch" block.  "pc" is the relative PC within the
855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * current method, indicating the offset from the start in 16-bit units.
856f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns the offset to the catch block, or -1 if we run up against a
858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * break frame without finding anything.
859f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
860f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The class resolution stuff we have to do while evaluating the "catch"
861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * blocks could cause an exception.  The caller should clear the exception
862f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * before calling here and restore it after.
863f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
864f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Sets *newFrame to the frame pointer of the frame with the catch block.
865f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If "scanOnly" is false, self->curFrame is also set to this value.
866f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
867f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint dvmFindCatchBlock(Thread* self, int relPc, Object* exception,
868f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool scanOnly, void** newFrame)
869f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
870f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    void* fp = self->curFrame;
871f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int catchAddr = -1;
872f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
873f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(!dvmCheckException(self));
874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (true) {
876f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        StackSaveArea* saveArea = SAVEAREA_FROM_FP(fp);
877f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        catchAddr = findCatchInMethod(self, saveArea->method, relPc,
878f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        exception->clazz);
879f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (catchAddr >= 0)
880f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
881f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
882f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
883f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Normally we'd check for ACC_SYNCHRONIZED methods and unlock
884f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * them as we unroll.  Dalvik uses what amount to generated
885f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * "finally" blocks to take care of this for us.
886f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
887f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
888f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* output method profiling info */
889f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!scanOnly) {
890f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            TRACE_METHOD_UNROLL(self, saveArea->method);
891f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
892f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
893f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
894f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Move up one frame.  If the next thing up is a break frame,
895f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * break out now so we're left unrolled to the last method frame.
896f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We need to point there so we can roll up the JNI local refs
897f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * if this was a native method.
898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
899f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(saveArea->prevFrame != NULL);
900fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro        if (dvmIsBreakFrame((u4*)saveArea->prevFrame)) {
901f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!scanOnly)
902f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;      // bail with catchAddr == -1
903f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
904f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
905f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * We're scanning for the debugger.  It needs to know if this
906f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * exception is going to be caught or not, and we need to figure
907f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * out if it will be caught *ever* not just between the current
908f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * position and the next break frame.  We can't tell what native
909f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * code is going to do, so we assume it never catches exceptions.
910f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             *
911f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Start by finding an interpreted code frame.
912f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
913f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            fp = saveArea->prevFrame;           // this is the break frame
914f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            saveArea = SAVEAREA_FROM_FP(fp);
915f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            fp = saveArea->prevFrame;           // this may be a good one
916f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            while (fp != NULL) {
917fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro                if (!dvmIsBreakFrame((u4*)fp)) {
918f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    saveArea = SAVEAREA_FROM_FP(fp);
919f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (!dvmIsNativeMethod(saveArea->method))
920f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        break;
921f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
922f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
923f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                fp = SAVEAREA_FROM_FP(fp)->prevFrame;
924f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
925f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (fp == NULL)
926f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;      // bail with catchAddr == -1
927f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
928f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
929f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Now fp points to the "good" frame.  When the interp code
930f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * invoked the native code, it saved a copy of its current PC
931f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * into xtra.currentPc.  Pull it out of there.
932f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
933f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            relPc =
934f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                saveArea->xtra.currentPc - SAVEAREA_FROM_FP(fp)->method->insns;
935f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
936f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            fp = saveArea->prevFrame;
937f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
938f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* savedPc in was-current frame goes with method in now-current */
939f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            relPc = saveArea->savedPc - SAVEAREA_FROM_FP(fp)->method->insns;
940f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
941f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
942f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
943f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!scanOnly)
944f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        self->curFrame = fp;
945f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
946f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
947f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The class resolution in findCatchInMethod() could cause an exception.
948f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Clear it to be safe.
949f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
950f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    self->exception = NULL;
951f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
952f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    *newFrame = fp;
953f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return catchAddr;
954f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
955f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
956f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
957f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We have to carry the exception's stack trace around, but in many cases
958f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * it will never be examined.  It makes sense to keep it in a compact,
959f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * VM-specific object, rather than an array of Objects with strings.
960f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
961f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Pass in the thread whose stack we're interested in.  If "thread" is
962f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * not self, the thread must be suspended.  This implies that the thread
963f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * list lock is held, which means we can't allocate objects or we risk
964f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * jamming the GC.  So, we allow this function to return different formats.
965f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (This shouldn't be called directly -- see the inline functions in the
966f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * header file.)
967f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
968f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If "wantObject" is true, this returns a newly-allocated Object, which is
969f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * presently an array of integers, but could become something else in the
970f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * future.  If "wantObject" is false, return plain malloc data.
971f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
972f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * NOTE: if we support class unloading, we will need to scan the class
973f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * object references out of these arrays.
974f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
975f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid* dvmFillInStackTraceInternal(Thread* thread, bool wantObject, int* pCount)
976f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
977f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ArrayObject* stackData = NULL;
978f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int* simpleData = NULL;
979f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    void* fp;
980f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    void* startFp;
981f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int stackDepth;
982f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int* intPtr;
983f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
984f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pCount != NULL)
985f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *pCount = 0;
986f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fp = thread->curFrame;
987f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
988f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(thread == dvmThreadSelf() || dvmIsSuspended(thread));
989f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
990f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
991f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We're looking at a stack frame for code running below a Throwable
992f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * constructor.  We want to remove the Throwable methods and the
993f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * superclass initializations so the user doesn't see them when they
994f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * read the stack dump.
995f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
996f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * TODO: this just scrapes off the top layers of Throwable.  Might not do
997f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the right thing if we create an exception object or cause a VM
998f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * exception while in a Throwable method.
999f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1000f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (fp != NULL) {
1001f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const StackSaveArea* saveArea = SAVEAREA_FROM_FP(fp);
1002f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const Method* method = saveArea->method;
1003f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1004fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro        if (dvmIsBreakFrame((u4*)fp))
1005f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1006f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!dvmInstanceof(method->clazz, gDvm.classJavaLangThrowable))
1007f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1008f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //LOGD("EXCEP: ignoring %s.%s\n",
1009f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //         method->clazz->descriptor, method->name);
1010f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fp = saveArea->prevFrame;
1011f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1012f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    startFp = fp;
1013f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1014f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1015f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Compute the stack depth.
1016f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1017f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    stackDepth = 0;
1018f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (fp != NULL) {
1019f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const StackSaveArea* saveArea = SAVEAREA_FROM_FP(fp);
1020f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1021fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro        if (!dvmIsBreakFrame((u4*)fp))
1022f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            stackDepth++;
1023f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1024f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(fp != saveArea->prevFrame);
1025f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fp = saveArea->prevFrame;
1026f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1027f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //LOGD("EXCEP: stack depth is %d\n", stackDepth);
1028f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1029f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!stackDepth)
1030f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
1031f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1032f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1033f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We need to store a pointer to the Method and the program counter.
1034f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We have 4-byte pointers, so we use '[I'.
1035f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1036f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (wantObject) {
1037f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(sizeof(Method*) == 4);
1038f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        stackData = dvmAllocPrimitiveArray('I', stackDepth*2, ALLOC_DEFAULT);
1039f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (stackData == NULL) {
1040f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(dvmCheckException(dvmThreadSelf()));
1041f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
1042f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1043f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        intPtr = (int*) stackData->contents;
1044f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
1045f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* array of ints; first entry is stack depth */
1046f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(sizeof(Method*) == sizeof(int));
1047f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        simpleData = (int*) malloc(sizeof(int) * stackDepth*2);
1048f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (simpleData == NULL)
1049f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
1050f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1051f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(pCount != NULL);
1052f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        intPtr = simpleData;
1053f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1054f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pCount != NULL)
1055f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *pCount = stackDepth;
1056f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1057f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fp = startFp;
1058f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (fp != NULL) {
1059f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const StackSaveArea* saveArea = SAVEAREA_FROM_FP(fp);
1060f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const Method* method = saveArea->method;
1061f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1062fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro        if (!dvmIsBreakFrame((u4*)fp)) {
1063f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //LOGD("EXCEP keeping %s.%s\n", method->clazz->descriptor,
1064f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //         method->name);
1065f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1066f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *intPtr++ = (int) method;
1067f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (dvmIsNativeMethod(method)) {
1068f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                *intPtr++ = 0;      /* no saved PC for native methods */
1069f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
1070f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                assert(saveArea->xtra.currentPc >= method->insns &&
1071de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro                        saveArea->xtra.currentPc <
1072f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        method->insns + dvmGetMethodInsnsSize(method));
1073f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                *intPtr++ = (int) (saveArea->xtra.currentPc - method->insns);
1074f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1075f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1076f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            stackDepth--;       // for verification
1077f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1078f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1079f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(fp != saveArea->prevFrame);
1080f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fp = saveArea->prevFrame;
1081f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1082f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(stackDepth == 0);
1083f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1084f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
1085f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (wantObject) {
1086f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmReleaseTrackedAlloc((Object*) stackData, dvmThreadSelf());
1087f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return stackData;
1088f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
1089f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return simpleData;
1090f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1091f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1092f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1093f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1094f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1095f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Given an Object previously created by dvmFillInStackTrace(), use the
1096f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * contents of the saved stack trace to generate an array of
1097f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * java/lang/StackTraceElement objects.
1098f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1099f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The returned array is not added to the "local refs" list.
1100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectArrayObject* dvmGetStackTrace(const Object* ostackData)
1102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const ArrayObject* stackData = (const ArrayObject*) ostackData;
1104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const int* intVals;
1105e3c01dac83e6eea7f82fe81ed89cfbdd9791dbc9Carl Shapiro    int stackSize;
1106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    stackSize = stackData->length / 2;
1108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    intVals = (const int*) stackData->contents;
1109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return dvmGetStackTraceRaw(intVals, stackSize);
1110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Generate an array of StackTraceElement objects from the raw integer
1114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * data encoded by dvmFillInStackTrace().
1115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "intVals" points to the first {method,pc} pair.
1117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
1118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The returned array is not added to the "local refs" list.
1119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectArrayObject* dvmGetStackTraceRaw(const int* intVals, int stackDepth)
1121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ArrayObject* steArray = NULL;
1123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
1124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* init this if we haven't yet */
1126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!dvmIsClassInitialized(gDvm.classJavaLangStackTraceElement))
1127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmInitClass(gDvm.classJavaLangStackTraceElement);
1128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* allocate a StackTraceElement array */
1130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    steArray = dvmAllocArray(gDvm.classJavaLangStackTraceElementArray,
1131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    stackDepth, kObjectArrayRefWidth, ALLOC_DEFAULT);
1132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (steArray == NULL)
1133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
1134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Allocate and initialize a StackTraceElement for each stack frame.
1137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We use the standard constructor to configure the object.
1138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < stackDepth; i++) {
1140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Object* ste;
1141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Method* meth;
1142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        StringObject* className;
1143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        StringObject* methodName;
1144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        StringObject* fileName;
1145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int lineNumber, pc;
1146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const char* sourceFile;
1147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char* dotName;
1148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ste = dvmAllocObject(gDvm.classJavaLangStackTraceElement,ALLOC_DEFAULT);
1150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (ste == NULL)
1151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
1152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        meth = (Method*) *intVals++;
1154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pc = *intVals++;
1155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pc == -1)      // broken top frame?
1157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            lineNumber = 0;
1158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        else
1159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            lineNumber = dvmLineNumFromPC(meth, pc);
1160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
11615016966b91f1bc36b2bd52ec13ecfd8de1c68209Elliott Hughes        dotName = dvmHumanReadableDescriptor(meth->clazz->descriptor);
116281f3ebe03cd33c9003641084bece0604ee68bf88Barry Hayes        className = dvmCreateStringFromCstr(dotName);
1163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        free(dotName);
1164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
116581f3ebe03cd33c9003641084bece0604ee68bf88Barry Hayes        methodName = dvmCreateStringFromCstr(meth->name);
1166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sourceFile = dvmGetMethodSourceFile(meth);
1167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (sourceFile != NULL)
116881f3ebe03cd33c9003641084bece0604ee68bf88Barry Hayes            fileName = dvmCreateStringFromCstr(sourceFile);
1169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        else
1170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            fileName = NULL;
1171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
1173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Invoke:
1174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *  public StackTraceElement(String declaringClass, String methodName,
1175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *      String fileName, int lineNumber)
1176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * (where lineNumber==-2 means "native")
1177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        JValue unused;
1179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmCallMethod(dvmThreadSelf(), gDvm.methJavaLangStackTraceElement_init,
1180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ste, &unused, className, methodName, fileName, lineNumber);
1181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmReleaseTrackedAlloc(ste, NULL);
1183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmReleaseTrackedAlloc((Object*) className, NULL);
1184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmReleaseTrackedAlloc((Object*) methodName, NULL);
1185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmReleaseTrackedAlloc((Object*) fileName, NULL);
1186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (dvmCheckException(dvmThreadSelf()))
1188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
1189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1190364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes        dvmSetObjectArrayElement(steArray, i, ste);
1191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
1194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmReleaseTrackedAlloc((Object*) steArray, NULL);
1195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return steArray;
1196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump the contents of a raw stack trace to the log.
1200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmLogRawStackTrace(const int* intVals, int stackDepth)
1202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
1204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Run through the array of stack frame data.
1207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < stackDepth; i++) {
1209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Method* meth;
1210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int lineNumber, pc;
1211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const char* sourceFile;
1212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char* dotName;
1213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        meth = (Method*) *intVals++;
1215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pc = *intVals++;
1216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pc == -1)      // broken top frame?
1218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            lineNumber = 0;
1219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        else
1220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            lineNumber = dvmLineNumFromPC(meth, pc);
1221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // probably don't need to do this, but it looks nicer
12235016966b91f1bc36b2bd52ec13ecfd8de1c68209Elliott Hughes        dotName = dvmHumanReadableDescriptor(meth->clazz->descriptor);
1224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (dvmIsNativeMethod(meth)) {
1226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGI("\tat %s.%s(Native Method)\n", dotName, meth->name);
1227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
1228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGI("\tat %s.%s(%s:%d)\n",
1229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dotName, meth->name, dvmGetMethodSourceFile(meth),
1230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmLineNumFromPC(meth, pc));
1231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        free(dotName);
1234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sourceFile = dvmGetMethodSourceFile(meth);
1236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
12408552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden * Get the message string.  We'd like to just grab the field out of
12418552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden * Throwable, but the getMessage() function can be overridden by the
12428552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden * sub-class.
12438552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden *
12448552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden * Returns the message string object, or NULL if it wasn't set or
12458552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden * we encountered a failure trying to retrieve it.  The string will
12468552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden * be added to the tracked references table.
12478552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden */
12488552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFaddenstatic StringObject* getExceptionMessage(Object* exception)
12498552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden{
12508552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden    Thread* self = dvmThreadSelf();
12518552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden    Method* getMessageMethod;
12528552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden    StringObject* messageStr = NULL;
12538552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden
12548552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden    assert(exception == self->exception);
125550cab51bb381c5da01adfd61954ddca37607f51eAndy McFadden    dvmAddTrackedAlloc(exception, self);
12568552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden    self->exception = NULL;
12578552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden
12588552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden    getMessageMethod = dvmFindVirtualMethodHierByDescriptor(exception->clazz,
12598552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden            "getMessage", "()Ljava/lang/String;");
12608552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden    if (getMessageMethod != NULL) {
12618552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden        /* could be in NATIVE mode from CheckJNI, so switch state */
12628552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden        ThreadStatus oldStatus = dvmChangeStatus(self, THREAD_RUNNING);
12638552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden        JValue result;
12648552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden
12658552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden        dvmCallMethod(self, getMessageMethod, exception, &result);
12668552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden        messageStr = (StringObject*) result.l;
1267bd74b4b51f16e200854e41bbbe5ee6afb3af4cffAndy McFadden        if (messageStr != NULL)
1268bd74b4b51f16e200854e41bbbe5ee6afb3af4cffAndy McFadden            dvmAddTrackedAlloc((Object*) messageStr, self);
12698552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden
12708552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden        dvmChangeStatus(self, oldStatus);
12718552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden    } else {
12728552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden        LOGW("WARNING: could not find getMessage in %s\n",
12738552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden            exception->clazz->descriptor);
12748552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden    }
12758552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden
12768552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden    if (self->exception != NULL) {
12778552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden        LOGW("NOTE: exception thrown while retrieving exception message: %s\n",
12788552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden            self->exception->clazz->descriptor);
12798552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden    }
12808552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden
12818552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden    self->exception = exception;
128250cab51bb381c5da01adfd61954ddca37607f51eAndy McFadden    dvmReleaseTrackedAlloc(exception, self);
12838552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden    return messageStr;
12848552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden}
12858552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden
12868552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden/*
1287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Print the direct stack trace of the given exception to the log.
1288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void logStackTraceOf(Object* exception)
1290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const ArrayObject* stackData;
1292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    StringObject* messageStr;
1293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int stackSize;
1294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const int* intVals;
1295de952db74f54108630a3dd24af0b38e583b62ed3Andy McFadden    char* className;
1296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
12975016966b91f1bc36b2bd52ec13ecfd8de1c68209Elliott Hughes    className = dvmHumanReadableDescriptor(exception->clazz->descriptor);
12988552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden    messageStr = getExceptionMessage(exception);
1299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (messageStr != NULL) {
1300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char* cp = dvmCreateCstrFromString(messageStr);
13018552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden        dvmReleaseTrackedAlloc((Object*) messageStr, dvmThreadSelf());
13028552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden        messageStr = NULL;
13038552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden
1304de952db74f54108630a3dd24af0b38e583b62ed3Andy McFadden        LOGI("%s: %s\n", className, cp);
1305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        free(cp);
1306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
1307de952db74f54108630a3dd24af0b38e583b62ed3Andy McFadden        LOGI("%s:\n", className);
1308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1309de952db74f54108630a3dd24af0b38e583b62ed3Andy McFadden    free(className);
1310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1311de952db74f54108630a3dd24af0b38e583b62ed3Andy McFadden    /*
1312de952db74f54108630a3dd24af0b38e583b62ed3Andy McFadden     * This relies on the stackState field, which contains the "raw"
1313de952db74f54108630a3dd24af0b38e583b62ed3Andy McFadden     * form of the stack.  The Throwable class may clear this field
1314de952db74f54108630a3dd24af0b38e583b62ed3Andy McFadden     * after it generates the "cooked" form, in which case we'll have
1315de952db74f54108630a3dd24af0b38e583b62ed3Andy McFadden     * nothing to show.
1316de952db74f54108630a3dd24af0b38e583b62ed3Andy McFadden     */
1317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    stackData = (const ArrayObject*) dvmGetFieldObject(exception,
1318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    gDvm.offJavaLangThrowable_stackState);
1319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (stackData == NULL) {
1320de952db74f54108630a3dd24af0b38e583b62ed3Andy McFadden        LOGI("  (raw stack trace not found)\n");
1321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
1322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    stackSize = stackData->length / 2;
1325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    intVals = (const int*) stackData->contents;
1326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLogRawStackTrace(intVals, stackSize);
1328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Print the stack trace of the current thread's exception, as well as
1332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the stack traces of any chained exceptions, to the log. We extract
1333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the stored stack trace and process it internally instead of calling
1334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * interpreted code.
1335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmLogExceptionStackTrace(void)
1337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object* exception = dvmThreadSelf()->exception;
1339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object* cause;
1340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (exception == NULL) {
1342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("tried to log a null exception?\n");
1343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
1344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (;;) {
1347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        logStackTraceOf(exception);
1348686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden        cause = dvmGetExceptionCause(exception);
1349686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden        if (cause == NULL) {
1350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGI("Caused by:\n");
1353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        exception = cause;
1354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
13560016024cdd2bdeef3b98c92f7a8f40a2bc1ff42dElliott Hughes
1357d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowAbstractMethodError(const char* msg) {
1358d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein    dvmThrowException("Ljava/lang/AbstractMethodError;", msg);
1359d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1360d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
1361d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowArithmeticException(const char* msg) {
1362d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein    dvmThrowException("Ljava/lang/ArithmeticException;", msg);
1363d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1364d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
136574501e600dcb5634aa26aee0a3f57f2b45b213f2Dan Bornsteinvoid dvmThrowArrayIndexOutOfBoundsException(int index, int length)
136674501e600dcb5634aa26aee0a3f57f2b45b213f2Dan Bornstein{
136774501e600dcb5634aa26aee0a3f57f2b45b213f2Dan Bornstein    dvmThrowExceptionFmt("Ljava/lang/ArrayIndexOutOfBoundsException;",
136874501e600dcb5634aa26aee0a3f57f2b45b213f2Dan Bornstein        "index=%d length=%d", index, length);
136974501e600dcb5634aa26aee0a3f57f2b45b213f2Dan Bornstein}
137074501e600dcb5634aa26aee0a3f57f2b45b213f2Dan Bornstein
137163644657f74e0a5d05f2c5fb56a18872e7ac7427Elliott Hughesstatic void dvmThrowTypeError(const char* exceptionClassName, const char* fmt,
137263644657f74e0a5d05f2c5fb56a18872e7ac7427Elliott Hughes    ClassObject* actual, ClassObject* desired)
1373c560e30f68265068bed9eadf174d1e76288d2952Elliott Hughes{
13745016966b91f1bc36b2bd52ec13ecfd8de1c68209Elliott Hughes    char* actualClassName = dvmHumanReadableDescriptor(actual->descriptor);
13755016966b91f1bc36b2bd52ec13ecfd8de1c68209Elliott Hughes    char* desiredClassName = dvmHumanReadableDescriptor(desired->descriptor);
137663644657f74e0a5d05f2c5fb56a18872e7ac7427Elliott Hughes    dvmThrowExceptionFmt(exceptionClassName, fmt,
1377c560e30f68265068bed9eadf174d1e76288d2952Elliott Hughes        actualClassName, desiredClassName);
1378c560e30f68265068bed9eadf174d1e76288d2952Elliott Hughes    free(desiredClassName);
1379c560e30f68265068bed9eadf174d1e76288d2952Elliott Hughes    free(actualClassName);
1380c560e30f68265068bed9eadf174d1e76288d2952Elliott Hughes}
138163644657f74e0a5d05f2c5fb56a18872e7ac7427Elliott Hughes
138263644657f74e0a5d05f2c5fb56a18872e7ac7427Elliott Hughesvoid dvmThrowArrayStoreException(ClassObject* actual, ClassObject* desired)
138363644657f74e0a5d05f2c5fb56a18872e7ac7427Elliott Hughes{
138463644657f74e0a5d05f2c5fb56a18872e7ac7427Elliott Hughes    dvmThrowTypeError("Ljava/lang/ArrayStoreException;",
138563644657f74e0a5d05f2c5fb56a18872e7ac7427Elliott Hughes        "%s cannot be stored in an array of type %s",
138663644657f74e0a5d05f2c5fb56a18872e7ac7427Elliott Hughes        actual, desired);
138763644657f74e0a5d05f2c5fb56a18872e7ac7427Elliott Hughes}
138863644657f74e0a5d05f2c5fb56a18872e7ac7427Elliott Hughes
138963644657f74e0a5d05f2c5fb56a18872e7ac7427Elliott Hughesvoid dvmThrowClassCastException(ClassObject* actual, ClassObject* desired)
139063644657f74e0a5d05f2c5fb56a18872e7ac7427Elliott Hughes{
139163644657f74e0a5d05f2c5fb56a18872e7ac7427Elliott Hughes    dvmThrowTypeError("Ljava/lang/ClassCastException;",
139263644657f74e0a5d05f2c5fb56a18872e7ac7427Elliott Hughes        "%s cannot be cast to %s", actual, desired);
139363644657f74e0a5d05f2c5fb56a18872e7ac7427Elliott Hughes}
1394d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
139570b00abc45d7d04342a96a03749f993028b060f7Dan Bornsteinvoid dvmThrowClassCircularityError(const char* descriptor) {
139670b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein    dvmThrowExceptionWithClassMessage("Ljava/lang/ClassCircularityError;",
139770b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein            descriptor);
139870b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein}
139970b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein
140070b00abc45d7d04342a96a03749f993028b060f7Dan Bornsteinvoid dvmThrowClassFormatError(const char* msg) {
140170b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein    dvmThrowException("Ljava/lang/ClassFormatError;", msg);
140270b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein}
140370b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein
1404d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowClassNotFoundException(const char* msg) {
1405d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein    dvmThrowException("Ljava/lang/ClassNotFoundException;", msg);
1406d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1407d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
1408d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowFileNotFoundException(const char* msg) {
1409d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein    dvmThrowException("Ljava/io/FileNotFoundException;", msg);
1410d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1411d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
1412d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowIOException(const char* msg) {
1413d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein    dvmThrowException("Ljava/io/IOException;", msg);
1414d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1415d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
1416d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowIllegalAccessException(const char* msg) {
1417d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein    dvmThrowException("Ljava/lang/IllegalAccessException;", msg);
1418d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1419d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
1420d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowIllegalAccessError(const char* msg) {
1421d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein    dvmThrowException("Ljava/lang/IllegalAccessError;", msg);
1422d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1423d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
1424d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowIllegalArgumentException(const char* msg) {
1425d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein    dvmThrowException("Ljava/lang/IllegalArgumentException;", msg);
1426d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1427d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
1428d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowIllegalMonitorStateException(const char* msg) {
1429d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein    dvmThrowException("Ljava/lang/IllegalMonitorStateException;", msg);
1430d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1431d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
1432d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowIllegalStateException(const char* msg) {
1433d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein    dvmThrowException("Ljava/lang/IllegalStateException;", msg);
1434d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1435d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
1436d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowIllegalThreadStateException(const char* msg) {
1437d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein    dvmThrowException("Ljava/lang/IllegalThreadStateException;", msg);
1438d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1439d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
144070b00abc45d7d04342a96a03749f993028b060f7Dan Bornsteinvoid dvmThrowIncompatibleClassChangeError(const char* msg) {
144170b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein    dvmThrowException("Ljava/lang/IncompatibleClassChangeError;", msg);
144270b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein}
144370b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein
144470b00abc45d7d04342a96a03749f993028b060f7Dan Bornsteinvoid dvmThrowIncompatibleClassChangeErrorWithClassMessage(
144570b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein        const char* descriptor)
144670b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein{
144770b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein    dvmThrowExceptionWithClassMessage(
144870b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein            "Ljava/lang/IncompatibleClassChangeError;", descriptor);
144970b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein}
145070b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein
1451d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowInternalError(const char* msg) {
1452d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein    dvmThrowException("Ljava/lang/InternalError;", msg);
1453d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1454d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
1455d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowInterruptedException(const char* msg) {
1456d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein    dvmThrowException("Ljava/lang/InterruptedException;", msg);
1457d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1458d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
145970b00abc45d7d04342a96a03749f993028b060f7Dan Bornsteinvoid dvmThrowLinkageError(const char* msg) {
146070b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein    dvmThrowException("Ljava/lang/LinkageError;", msg);
146170b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein}
146270b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein
1463d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowNegativeArraySizeException(const char* msg) {
1464d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein    dvmThrowException("Ljava/lang/NegativeArraySizeException;", msg);
1465d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1466d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
1467d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowNoClassDefFoundError(const char* descriptor) {
1468d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein    dvmThrowExceptionWithClassMessage("Ljava/lang/NoClassDefFoundError;",
1469d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein            descriptor);
1470d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1471d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
1472d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowNoSuchFieldError(const char* msg) {
1473d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein    dvmThrowException("Ljava/lang/NoSuchFieldError;", msg);
1474d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1475d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
1476d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowNoSuchFieldException(const char* msg) {
1477d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein    dvmThrowException("Ljava/lang/NoSuchFieldException;", msg);
1478d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1479d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
1480d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowNoSuchMethodError(const char* msg) {
1481d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein    dvmThrowException("Ljava/lang/NoSuchMethodError;", msg);
1482d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1483d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
1484d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowNullPointerException(const char* msg) {
1485d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein    dvmThrowException("Ljava/lang/NullPointerException;", msg);
1486d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1487d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
1488d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowOutOfMemoryError(const char* msg) {
1489d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein    dvmThrowException("Ljava/lang/OutOfMemoryError;", msg);
1490d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1491d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
1492d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowRuntimeException(const char* msg) {
1493d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein    dvmThrowException("Ljava/lang/RuntimeException;", msg);
1494d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1495d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
149674501e600dcb5634aa26aee0a3f57f2b45b213f2Dan Bornsteinvoid dvmThrowStaleDexCacheError(const char* msg) {
149774501e600dcb5634aa26aee0a3f57f2b45b213f2Dan Bornstein    dvmThrowException("Ldalvik/system/StaleDexCacheError;", msg);
149874501e600dcb5634aa26aee0a3f57f2b45b213f2Dan Bornstein}
149974501e600dcb5634aa26aee0a3f57f2b45b213f2Dan Bornstein
1500d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowStringIndexOutOfBoundsException(const char* msg) {
1501d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein    dvmThrowException("Ljava/lang/StringIndexOutOfBoundsException;", msg);
1502d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1503d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
150470b00abc45d7d04342a96a03749f993028b060f7Dan Bornsteinvoid dvmThrowUnsatisfiedLinkError(const char* msg) {
150570b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein    dvmThrowException("Ljava/lang/UnsatisfiedLinkError;", msg);
150670b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein}
150770b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein
1508d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowUnsupportedOperationException(const char* msg) {
1509d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein    dvmThrowException("Ljava/lang/UnsupportedOperationException;", msg);
1510d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
151170b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein
151270b00abc45d7d04342a96a03749f993028b060f7Dan Bornsteinvoid dvmThrowVirtualMachineError(const char* msg) {
151370b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein    dvmThrowException("Ljava/lang/VirtualMachineError;", msg);
151470b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein}
1515