Exception.cpp revision 6f3c21fb026d9489e5046416bcd5a84fa8e4615b
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
1020b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornsteinvoid dvmThrowExceptionFmtV(ClassObject* exceptionClass,
1036d167a4b02f310700a55fc9a24fccce999e0fdf2Dan Bornstein    const char* fmt, va_list args)
1046d167a4b02f310700a55fc9a24fccce999e0fdf2Dan Bornstein{
1056d167a4b02f310700a55fc9a24fccce999e0fdf2Dan Bornstein    char msgBuf[512];
1066d167a4b02f310700a55fc9a24fccce999e0fdf2Dan Bornstein
1076d167a4b02f310700a55fc9a24fccce999e0fdf2Dan Bornstein    vsnprintf(msgBuf, sizeof(msgBuf), fmt, args);
1080b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornstein    dvmThrowChainedException(exceptionClass, msgBuf, NULL);
1096d167a4b02f310700a55fc9a24fccce999e0fdf2Dan Bornstein}
1106d167a4b02f310700a55fc9a24fccce999e0fdf2Dan Bornstein
1110b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornsteinvoid dvmThrowChainedException(ClassObject* excepClass, const char* msg,
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object* cause)
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Thread* self = dvmThreadSelf();
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object* exception;
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1172c8e25b2010d1bba4dca0148691bc6e1a4ee7616Dan Bornstein    if (excepClass == NULL) {
1182c8e25b2010d1bba4dca0148691bc6e1a4ee7616Dan Bornstein        /*
1192c8e25b2010d1bba4dca0148691bc6e1a4ee7616Dan Bornstein         * The exception class was passed in as NULL. This might happen
1202c8e25b2010d1bba4dca0148691bc6e1a4ee7616Dan Bornstein         * early on in VM initialization. There's nothing better to do
1212c8e25b2010d1bba4dca0148691bc6e1a4ee7616Dan Bornstein         * than just log the message as an error and abort.
1222c8e25b2010d1bba4dca0148691bc6e1a4ee7616Dan Bornstein         */
12360fc806b679a3655c228b4093058c59941a49cfeDan Bornstein        LOGE("Fatal error: %s", msg);
1242c8e25b2010d1bba4dca0148691bc6e1a4ee7616Dan Bornstein        dvmAbort();
1252c8e25b2010d1bba4dca0148691bc6e1a4ee7616Dan Bornstein    }
1262c8e25b2010d1bba4dca0148691bc6e1a4ee7616Dan Bornstein
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* make sure the exception is initialized */
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!dvmIsClassInitialized(excepClass) && !dvmInitClass(excepClass)) {
12960fc806b679a3655c228b4093058c59941a49cfeDan Bornstein        LOGE("ERROR: unable to initialize exception class '%s'",
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            excepClass->descriptor);
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (strcmp(excepClass->descriptor, "Ljava/lang/InternalError;") == 0)
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmAbort();
1330b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornstein        dvmThrowChainedException(gDvm.exInternalError,
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "failed to init original exception class", cause);
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    exception = dvmAllocObject(excepClass, ALLOC_DEFAULT);
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (exception == NULL) {
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We're in a lot of trouble.  We might be in the process of
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * throwing an out-of-memory exception, in which case the
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * pre-allocated object will have been thrown when our object alloc
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * failed.  So long as there's an exception raised, return and
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * allow the system to try to recover.  If not, something is broken
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * and we need to bail out.
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (dvmCheckException(self))
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
15060fc806b679a3655c228b4093058c59941a49cfeDan Bornstein        LOGE("FATAL: unable to allocate exception '%s' '%s'",
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            excepClass->descriptor, msg != NULL ? msg : "(no msg)");
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmAbort();
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Init the exception.
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.optimizing) {
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* need the exception object, but can't invoke interpreted code */
16060fc806b679a3655c228b4093058c59941a49cfeDan Bornstein        LOGV("Skipping init of exception %s '%s'",
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            excepClass->descriptor, msg);
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(excepClass == exception->clazz);
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!initException(exception, msg, cause, self)) {
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Whoops.  If we can't initialize the exception, we can't use
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * it.  If there's an exception already set, the constructor
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * probably threw an OutOfMemoryError.
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!dvmCheckException(self)) {
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /*
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * We're required to throw something, so we just
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * throw the pre-constructed internal error.
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                self->exception = gDvm.internalErrorObj;
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    self->exception = exception;
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmReleaseTrackedAlloc(exception, self);
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1870b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornsteinvoid dvmThrowChainedExceptionWithClassMessage(
188a3b3512e99ef51940b0a13e57528bd32803f72b4Dan Bornstein    ClassObject* exceptionClass, const char* messageDescriptor,
189a3b3512e99ef51940b0a13e57528bd32803f72b4Dan Bornstein    Object* cause)
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* message = dvmDescriptorToName(messageDescriptor);
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1930b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornstein    dvmThrowChainedException(exceptionClass, message, cause);
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(message);
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1984a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein * Find and return an exception constructor method that can take the
1994a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein * indicated parameters, or return NULL if no such constructor exists.
2004a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein */
2014a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornsteinstatic Method* findExceptionInitMethod(ClassObject* excepClass,
2024a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein    bool hasMessage, bool hasCause)
2034a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein{
2044a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein    if (hasMessage) {
2054a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein        Method* result;
2064a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein
2074a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein        if (hasCause) {
2084a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein            result = dvmFindDirectMethodByDescriptor(
2094a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein                    excepClass, "<init>",
2104a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein                    "(Ljava/lang/String;Ljava/lang/Throwable;)V");
2114a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein        } else {
2124a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein            result = dvmFindDirectMethodByDescriptor(
2134a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein                    excepClass, "<init>", "(Ljava/lang/String;)V");
2144a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein        }
2154a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein
2164a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein        if (result != NULL) {
2174a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein            return result;
2184a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein        }
2194a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein
2204a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein        if (hasCause) {
2214a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein            return dvmFindDirectMethodByDescriptor(
2224a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein                    excepClass, "<init>",
2234a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein                    "(Ljava/lang/Object;Ljava/lang/Throwable;)V");
2244a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein        } else {
2254a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein            return dvmFindDirectMethodByDescriptor(
2264a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein                    excepClass, "<init>", "(Ljava/lang/Object;)V");
2274a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein        }
2284a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein    } else if (hasCause) {
2294a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein        return dvmFindDirectMethodByDescriptor(
2304a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein                excepClass, "<init>", "(Ljava/lang/Throwable;)V");
2314a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein    } else {
2324a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein        return dvmFindDirectMethodByDescriptor(excepClass, "<init>", "()V");
2334a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein    }
2344a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein}
2354a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein
2364a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein/*
237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Initialize an exception with an appropriate constructor.
238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "exception" is the exception object to initialize.
240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Either or both of "msg" and "cause" may be null.
241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "self" is dvmThreadSelf(), passed in so we don't have to look it up again.
242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If the process of initializing the exception causes another
244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * exception (e.g., OutOfMemoryError) to be thrown, return an error
245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and leave self->exception intact.
246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool initException(Object* exception, const char* msg, Object* cause,
248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Thread* self)
249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    enum {
251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        kInitUnknown,
252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        kInitNoarg,
253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        kInitMsg,
254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        kInitMsgThrow,
255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        kInitThrow
256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } initKind = kInitUnknown;
257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Method* initMethod = NULL;
258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* excepClass = exception->clazz;
259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    StringObject* msgStr = NULL;
260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool result = false;
261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool needInitCause = false;
262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(self != NULL);
264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(self->exception == NULL);
265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* if we have a message, create a String */
267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (msg == NULL)
268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        msgStr = NULL;
269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    else {
27081f3ebe03cd33c9003641084bece0604ee68bf88Barry Hayes        msgStr = dvmCreateStringFromCstr(msg);
271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (msgStr == NULL) {
272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGW("Could not allocate message string \"%s\" while "
2736f3c21fb026d9489e5046416bcd5a84fa8e4615bDan Bornstein                    "throwing internal exception (%s)",
274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    msg, excepClass->descriptor);
275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
279686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden    if (cause != NULL) {
28032bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein        if (!dvmInstanceof(cause->clazz, gDvm.exThrowable)) {
28160fc806b679a3655c228b4093058c59941a49cfeDan Bornstein            LOGE("Tried to init exception with cause '%s'",
282686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden                cause->clazz->descriptor);
283686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden            dvmAbort();
284686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden        }
285686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden    }
286686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden
287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The Throwable class has four public constructors:
289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *  (1) Throwable()
290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *  (2) Throwable(String message)
291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *  (3) Throwable(String message, Throwable cause)  (added in 1.4)
292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *  (4) Throwable(Throwable cause)                  (added in 1.4)
293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The first two are part of the original design, and most exception
295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * classes should support them.  The third prototype was used by
296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * individual exceptions. e.g. ClassNotFoundException added it in 1.2.
297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The general "cause" mechanism was added in 1.4.  Some classes,
298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * such as IllegalArgumentException, initially supported the first
299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * two, but added the second two in a later release.
300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Exceptions may be picky about how their "cause" field is initialized.
302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * If you call ClassNotFoundException(String), it may choose to
303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * initialize its "cause" field to null.  Doing so prevents future
304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * calls to Throwable.initCause().
305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * So, if "cause" is not NULL, we need to look for a constructor that
307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * takes a throwable.  If we can't find one, we fall back on calling
308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * #1/#2 and making a separate call to initCause().  Passing a null ref
309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * for "message" into Throwable(String, Throwable) is allowed, but we
310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * prefer to use the Throwable-only version because it has different
311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * behavior.
312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * java.lang.TypeNotPresentException is a strange case -- it has #3 but
314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * not #2.  (Some might argue that the constructor is actually not #3,
315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * because it doesn't take the message string as an argument, but it
316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * has the same effect and we can work with it here.)
3174a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein     *
3184a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein     * java.lang.AssertionError is also a strange case -- it has a
3194a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein     * constructor that takes an Object, but not one that takes a String.
3204a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein     * There may be other cases like this, as well, so we generally look
3214a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein     * for an Object-taking constructor if we can't find one that takes
3224a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein     * a String.
323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (cause == NULL) {
325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (msgStr == NULL) {
3264a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein            initMethod = findExceptionInitMethod(excepClass, false, false);
327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            initKind = kInitNoarg;
328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
3294a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein            initMethod = findExceptionInitMethod(excepClass, true, false);
330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (initMethod != NULL) {
331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                initKind = kInitMsg;
332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* no #2, try #3 */
3344a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein                initMethod = findExceptionInitMethod(excepClass, true, true);
3354a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein                if (initMethod != NULL) {
336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    initKind = kInitMsgThrow;
3374a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein                }
338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (msgStr == NULL) {
3424a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein            initMethod = findExceptionInitMethod(excepClass, false, true);
343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (initMethod != NULL) {
344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                initKind = kInitThrow;
345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
3464a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein                initMethod = findExceptionInitMethod(excepClass, false, false);
347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                initKind = kInitNoarg;
348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                needInitCause = true;
349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
3514a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein            initMethod = findExceptionInitMethod(excepClass, true, true);
352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (initMethod != NULL) {
353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                initKind = kInitMsgThrow;
354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
3554a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein                initMethod = findExceptionInitMethod(excepClass, true, false);
356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                initKind = kInitMsg;
357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                needInitCause = true;
358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (initMethod == NULL) {
363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We can't find the desired constructor.  This can happen if a
365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * subclass of java/lang/Throwable doesn't define an expected
366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * constructor, e.g. it doesn't provide one that takes a string
367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * when a message has been provided.
368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("WARNING: exception class '%s' missing constructor "
3706f3c21fb026d9489e5046416bcd5a84fa8e4615bDan Bornstein            "(msg='%s' kind=%d)",
371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            excepClass->descriptor, msg, initKind);
372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(strcmp(excepClass->descriptor,
373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                      "Ljava/lang/RuntimeException;") != 0);
3740b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornstein        dvmThrowChainedException(gDvm.exRuntimeException,
375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "re-throw on exception class missing constructor", NULL);
376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Call the constructor with the appropriate arguments.
381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    JValue unused;
383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    switch (initKind) {
384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kInitNoarg:
38560fc806b679a3655c228b4093058c59941a49cfeDan Bornstein        LOGVV("+++ exc noarg (ic=%d)", needInitCause);
386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmCallMethod(self, initMethod, exception, &unused);
387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kInitMsg:
38960fc806b679a3655c228b4093058c59941a49cfeDan Bornstein        LOGVV("+++ exc msg (ic=%d)", needInitCause);
390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmCallMethod(self, initMethod, exception, &unused, msgStr);
391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kInitThrow:
393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("+++ exc throw");
394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(!needInitCause);
395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmCallMethod(self, initMethod, exception, &unused, cause);
396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    case kInitMsgThrow:
398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGVV("+++ exc msg+throw");
399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(!needInitCause);
400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmCallMethod(self, initMethod, exception, &unused, msgStr, cause);
401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        break;
402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    default:
403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(false);
404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * It's possible the constructor has thrown an exception.  If so, we
409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * return an error and let our caller deal with it.
410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (self->exception != NULL) {
41260fc806b679a3655c228b4093058c59941a49cfeDan Bornstein        LOGW("Exception thrown (%s) while throwing internal exception (%s)",
413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            self->exception->clazz->descriptor, exception->clazz->descriptor);
414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * If this exception was caused by another exception, and we weren't
419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * able to find a cause-setting constructor, set the "cause" field
420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * with an explicit call.
421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (needInitCause) {
423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Method* initCause;
424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        initCause = dvmFindVirtualMethodHierByDescriptor(excepClass, "initCause",
425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            "(Ljava/lang/Throwable;)Ljava/lang/Throwable;");
426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (initCause != NULL) {
427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmCallMethod(self, initCause, exception, &unused, cause);
428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (self->exception != NULL) {
429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* initCause() threw an exception; return an error and
430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * let the caller deal with it.
431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                LOGW("Exception thrown (%s) during initCause() "
4336f3c21fb026d9489e5046416bcd5a84fa8e4615bDan Bornstein                        "of internal exception (%s)",
434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        self->exception->clazz->descriptor,
435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        exception->clazz->descriptor);
436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                goto bail;
437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
43960fc806b679a3655c228b4093058c59941a49cfeDan Bornstein            LOGW("WARNING: couldn't find initCause in '%s'",
440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                excepClass->descriptor);
441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    result = true;
446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmReleaseTrackedAlloc((Object*) msgStr, self);     // NULL is ok
449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return result;
450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
4549807b4e9412a6ce6863688c84a36ce294028ff04Dan Bornstein * Clear the pending exception. This is used by the optimization and
4559807b4e9412a6ce6863688c84a36ce294028ff04Dan Bornstein * verification code, which mostly happens during runs of dexopt.
456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This can also be called when the VM is in a "normal" state, e.g. when
4589807b4e9412a6ce6863688c84a36ce294028ff04Dan Bornstein * verifying classes that couldn't be verified at optimization time.
459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmClearOptException(Thread* self)
461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    self->exception = NULL;
463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns "true" if this is a "checked" exception, i.e. it's a subclass
467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * of Throwable (assumed) but not a subclass of RuntimeException or Error.
468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmIsCheckedException(const Object* exception)
470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
47132bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein    if (dvmInstanceof(exception->clazz, gDvm.exError) ||
47232bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein        dvmInstanceof(exception->clazz, gDvm.exRuntimeException))
473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return true;
477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Wrap the now-pending exception in a different exception.  This is useful
482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * for reflection stuff that wants to hand a checked exception back from a
483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * method that doesn't declare it.
484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If something fails, an (unchecked) exception related to that failure
486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * will be pending instead.
487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmWrapException(const char* newExcepStr)
489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Thread* self = dvmThreadSelf();
491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object* origExcep;
492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* iteClass;
493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    origExcep = dvmGetException(self);
495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmAddTrackedAlloc(origExcep, self);    // don't let the GC free it
496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmClearException(self);                // clear before class lookup
498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    iteClass = dvmFindSystemClass(newExcepStr);
499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (iteClass != NULL) {
500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Object* iteExcep;
501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Method* initMethod;
502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        iteExcep = dvmAllocObject(iteClass, ALLOC_DEFAULT);
504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (iteExcep != NULL) {
505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            initMethod = dvmFindDirectMethodByDescriptor(iteClass, "<init>",
506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            "(Ljava/lang/Throwable;)V");
507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (initMethod != NULL) {
508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                JValue unused;
509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmCallMethod(self, initMethod, iteExcep, &unused,
510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    origExcep);
511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* if <init> succeeded, replace the old exception */
513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (!dvmCheckException(self))
514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    dvmSetException(self, iteExcep);
515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmReleaseTrackedAlloc(iteExcep, NULL);
517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* if initMethod doesn't exist, or failed... */
519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!dvmCheckException(self))
520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmSetException(self, origExcep);
521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* leave OutOfMemoryError pending */
523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* leave ClassNotFoundException pending */
526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(dvmCheckException(self));
529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmReleaseTrackedAlloc(origExcep, self);
530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
533686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden * Get the "cause" field from an exception.
534686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden *
535686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden * The Throwable class initializes the "cause" field to "this" to
536686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden * differentiate between being initialized to null and never being
537686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden * initialized.  We check for that here and convert it to NULL.
538686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden */
539686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFaddenObject* dvmGetExceptionCause(const Object* exception)
540686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden{
54132bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein    if (!dvmInstanceof(exception->clazz, gDvm.exThrowable)) {
54260fc806b679a3655c228b4093058c59941a49cfeDan Bornstein        LOGE("Tried to get cause from object of type '%s'",
543686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden            exception->clazz->descriptor);
544686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden        dvmAbort();
545686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden    }
546686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden    Object* cause =
547686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden        dvmGetFieldObject(exception, gDvm.offJavaLangThrowable_cause);
548686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden    if (cause == exception)
549686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden        return NULL;
550686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden    else
551686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden        return cause;
552686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden}
553686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden
554686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden/*
555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Print the stack trace of the current exception on stderr.  This is called
556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * from the JNI ExceptionDescribe call.
557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * For consistency we just invoke the Throwable printStackTrace method,
559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * which might be overridden in the exception object.
560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Exceptions thrown during the course of printing the stack trace are
562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ignored.
563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
5641e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirovoid dvmPrintExceptionStackTrace()
565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Thread* self = dvmThreadSelf();
567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object* exception;
568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Method* printMethod;
569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    exception = self->exception;
571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (exception == NULL)
572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
57450cab51bb381c5da01adfd61954ddca37607f51eAndy McFadden    dvmAddTrackedAlloc(exception, self);
575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    self->exception = NULL;
576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printMethod = dvmFindVirtualMethodHierByDescriptor(exception->clazz,
577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    "printStackTrace", "()V");
578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (printMethod != NULL) {
579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        JValue unused;
580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmCallMethod(self, printMethod, exception, &unused);
581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
58260fc806b679a3655c228b4093058c59941a49cfeDan Bornstein        LOGW("WARNING: could not find printStackTrace in %s",
583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            exception->clazz->descriptor);
584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (self->exception != NULL) {
58760fc806b679a3655c228b4093058c59941a49cfeDan Bornstein        LOGW("NOTE: exception thrown while printing stack trace: %s",
588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            self->exception->clazz->descriptor);
589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    self->exception = exception;
59250cab51bb381c5da01adfd61954ddca37607f51eAndy McFadden    dvmReleaseTrackedAlloc(exception, self);
593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Search the method's list of exceptions for a match.
597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns the offset of the catch block on success, or -1 on failure.
599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int findCatchInMethod(Thread* self, const Method* method, int relPc,
601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ClassObject* excepClass)
602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Need to clear the exception before entry.  Otherwise, dvmResolveClass
605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * might think somebody threw an exception while it was loading a class.
606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(!dvmCheckException(self));
608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(!dvmIsNativeMethod(method));
609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
61060fc806b679a3655c228b4093058c59941a49cfeDan Bornstein    LOGVV("findCatchInMethod %s.%s excep=%s depth=%d",
611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        method->clazz->descriptor, method->name, excepClass->descriptor,
61230bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee        dvmComputeExactFrameDepth(self->interpSave.curFrame));
613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DvmDex* pDvmDex = method->clazz->pDvmDex;
615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const DexCode* pCode = dvmGetMethodCode(method);
616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DexCatchIterator iterator;
617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dexFindCatchHandler(&iterator, pCode, relPc)) {
619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (;;) {
620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            DexCatchHandler* handler = dexCatchIteratorNext(&iterator);
621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (handler == NULL) {
623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
625de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (handler->typeIdx == kDexNoIndex) {
627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /* catch-all */
62860fc806b679a3655c228b4093058c59941a49cfeDan Bornstein                LOGV("Match on catch-all block at 0x%02x in %s.%s for %s",
629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        relPc, method->clazz->descriptor,
630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        method->name, excepClass->descriptor);
631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return handler->address;
632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ClassObject* throwable =
635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmDexGetResolvedClass(pDvmDex, handler->typeIdx);
636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (throwable == NULL) {
637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /*
638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * TODO: this behaves badly if we run off the stack
639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * while trying to throw an exception.  The problem is
640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * that, if we're in a class loaded by a class loader,
641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * the call to dvmResolveClass has to ask the class
642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * loader for help resolving any previously-unresolved
643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * classes.  If this particular class loader hasn't
644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * resolved StackOverflowError, it will call into
645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * interpreted code, and blow up.
646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 *
647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * We currently replace the previous exception with
648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * the StackOverflowError, which means they won't be
649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * catching it *unless* they explicitly catch
650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * StackOverflowError, in which case we'll be unable
651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * to resolve the class referred to by the "catch"
652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * block.
653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 *
654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * We end up getting a huge pile of warnings if we do
655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * a simple synthetic test, because this method gets
656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * called on every stack frame up the tree, and it
657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * fails every time.
658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 *
659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * This eventually bails out, effectively becoming an
660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * uncatchable exception, so other than the flurry of
661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * warnings it's not really a problem.  Still, we could
662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * probably handle this better.
663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                throwable = dvmResolveClass(method->clazz, handler->typeIdx,
665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    true);
666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (throwable == NULL) {
667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    /*
668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     * We couldn't find the exception they wanted in
669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     * our class files (or, perhaps, the stack blew up
670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     * while we were querying a class loader). Cough
671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     * up a warning, then move on to the next entry.
672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     * Keep the exception status clear.
673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     */
674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    LOGW("Could not resolve class ref'ed in exception "
6756f3c21fb026d9489e5046416bcd5a84fa8e4615bDan Bornstein                            "catch list (class index %d, exception %s)",
676f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            handler->typeIdx,
677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            (self->exception != NULL) ?
678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            self->exception->clazz->descriptor : "(none)");
679f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    dvmClearException(self);
680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    continue;
681f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
683f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
68460fc806b679a3655c228b4093058c59941a49cfeDan Bornstein            //LOGD("ADDR MATCH, check %s instanceof %s",
685f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //    excepClass->descriptor, pEntry->excepClass->descriptor);
686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (dvmInstanceof(excepClass, throwable)) {
68860fc806b679a3655c228b4093058c59941a49cfeDan Bornstein                LOGV("Match on catch block at 0x%02x in %s.%s for %s",
689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        relPc, method->clazz->descriptor,
690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        method->name, excepClass->descriptor);
691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return handler->address;
692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
69660fc806b679a3655c228b4093058c59941a49cfeDan Bornstein    LOGV("No matching catch block at 0x%02x in %s for %s",
697f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        relPc, method->name, excepClass->descriptor);
698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return -1;
699f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
700f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
701f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
702f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Find a matching "catch" block.  "pc" is the relative PC within the
703f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * current method, indicating the offset from the start in 16-bit units.
704f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
705f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns the offset to the catch block, or -1 if we run up against a
706f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * break frame without finding anything.
707f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
708f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The class resolution stuff we have to do while evaluating the "catch"
709f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * blocks could cause an exception.  The caller should clear the exception
710f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * before calling here and restore it after.
711f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
712f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Sets *newFrame to the frame pointer of the frame with the catch block.
71330bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee * If "scanOnly" is false, self->interpSave.curFrame is also set to this value.
714f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
715f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint dvmFindCatchBlock(Thread* self, int relPc, Object* exception,
716f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool scanOnly, void** newFrame)
717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
71830bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee    u4* fp = self->interpSave.curFrame;
719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int catchAddr = -1;
720f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
721f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(!dvmCheckException(self));
722f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
723f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (true) {
724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        StackSaveArea* saveArea = SAVEAREA_FROM_FP(fp);
725f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        catchAddr = findCatchInMethod(self, saveArea->method, relPc,
726f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        exception->clazz);
727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (catchAddr >= 0)
728f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Normally we'd check for ACC_SYNCHRONIZED methods and unlock
732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * them as we unroll.  Dalvik uses what amount to generated
733f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * "finally" blocks to take care of this for us.
734f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
735f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
736f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* output method profiling info */
737f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!scanOnly) {
738f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            TRACE_METHOD_UNROLL(self, saveArea->method);
739f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
740f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
741f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
742f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Move up one frame.  If the next thing up is a break frame,
743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * break out now so we're left unrolled to the last method frame.
744f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * We need to point there so we can roll up the JNI local refs
745f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * if this was a native method.
746f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
747f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(saveArea->prevFrame != NULL);
748fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro        if (dvmIsBreakFrame((u4*)saveArea->prevFrame)) {
749f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!scanOnly)
750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;      // bail with catchAddr == -1
751f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
752f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
753f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * We're scanning for the debugger.  It needs to know if this
754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * exception is going to be caught or not, and we need to figure
755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * out if it will be caught *ever* not just between the current
756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * position and the next break frame.  We can't tell what native
757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * code is going to do, so we assume it never catches exceptions.
758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             *
759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Start by finding an interpreted code frame.
760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            fp = saveArea->prevFrame;           // this is the break frame
762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            saveArea = SAVEAREA_FROM_FP(fp);
763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            fp = saveArea->prevFrame;           // this may be a good one
764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            while (fp != NULL) {
765fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro                if (!dvmIsBreakFrame((u4*)fp)) {
766f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    saveArea = SAVEAREA_FROM_FP(fp);
767f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (!dvmIsNativeMethod(saveArea->method))
768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        break;
769f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
770f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
771f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                fp = SAVEAREA_FROM_FP(fp)->prevFrame;
772f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
773f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (fp == NULL)
774f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;      // bail with catchAddr == -1
775f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
776f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
777f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Now fp points to the "good" frame.  When the interp code
778f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * invoked the native code, it saved a copy of its current PC
779f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * into xtra.currentPc.  Pull it out of there.
780f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
781f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            relPc =
782f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                saveArea->xtra.currentPc - SAVEAREA_FROM_FP(fp)->method->insns;
783f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
784f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            fp = saveArea->prevFrame;
785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
786f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* savedPc in was-current frame goes with method in now-current */
787f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            relPc = saveArea->savedPc - SAVEAREA_FROM_FP(fp)->method->insns;
788f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!scanOnly)
79230bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee        self->interpSave.curFrame = fp;
793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
794f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The class resolution in findCatchInMethod() could cause an exception.
796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Clear it to be safe.
797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    self->exception = NULL;
799f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    *newFrame = fp;
801f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return catchAddr;
802f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
803f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
804f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We have to carry the exception's stack trace around, but in many cases
806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * it will never be examined.  It makes sense to keep it in a compact,
807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * VM-specific object, rather than an array of Objects with strings.
808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Pass in the thread whose stack we're interested in.  If "thread" is
810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * not self, the thread must be suspended.  This implies that the thread
811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * list lock is held, which means we can't allocate objects or we risk
812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * jamming the GC.  So, we allow this function to return different formats.
813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (This shouldn't be called directly -- see the inline functions in the
814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * header file.)
815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If "wantObject" is true, this returns a newly-allocated Object, which is
817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * presently an array of integers, but could become something else in the
818f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * future.  If "wantObject" is false, return plain malloc data.
819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * NOTE: if we support class unloading, we will need to scan the class
821f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * object references out of these arrays.
822f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
8236b1f9f877b70fcc5375fa33a445ac84777757eb2Brian Carlstromvoid* dvmFillInStackTraceInternal(Thread* thread, bool wantObject, size_t* pCount)
824f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
825f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ArrayObject* stackData = NULL;
826f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int* simpleData = NULL;
827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    void* fp;
828f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    void* startFp;
8296b1f9f877b70fcc5375fa33a445ac84777757eb2Brian Carlstrom    size_t stackDepth;
830f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int* intPtr;
831f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
832f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pCount != NULL)
833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *pCount = 0;
83430bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee    fp = thread->interpSave.curFrame;
835f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
836f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(thread == dvmThreadSelf() || dvmIsSuspended(thread));
837f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
838f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
839f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We're looking at a stack frame for code running below a Throwable
840f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * constructor.  We want to remove the Throwable methods and the
841f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * superclass initializations so the user doesn't see them when they
842f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * read the stack dump.
843f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
844f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * TODO: this just scrapes off the top layers of Throwable.  Might not do
845f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the right thing if we create an exception object or cause a VM
846f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * exception while in a Throwable method.
847f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (fp != NULL) {
849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const StackSaveArea* saveArea = SAVEAREA_FROM_FP(fp);
850f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const Method* method = saveArea->method;
851f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
852fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro        if (dvmIsBreakFrame((u4*)fp))
853f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
85432bb3da6f05959749161ce7f9103027f11597fe3Dan Bornstein        if (!dvmInstanceof(method->clazz, gDvm.exThrowable))
855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
85660fc806b679a3655c228b4093058c59941a49cfeDan Bornstein        //LOGD("EXCEP: ignoring %s.%s",
857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        //         method->clazz->descriptor, method->name);
858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fp = saveArea->prevFrame;
859f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
860f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    startFp = fp;
861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
862f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
863f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Compute the stack depth.
864f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
865f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    stackDepth = 0;
866f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (fp != NULL) {
867f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const StackSaveArea* saveArea = SAVEAREA_FROM_FP(fp);
868f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
869fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro        if (!dvmIsBreakFrame((u4*)fp))
870f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            stackDepth++;
871f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
872f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(fp != saveArea->prevFrame);
873f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fp = saveArea->prevFrame;
874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
87560fc806b679a3655c228b4093058c59941a49cfeDan Bornstein    //LOGD("EXCEP: stack depth is %d", stackDepth);
876f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
877f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!stackDepth)
878f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
879f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
880f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
881f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We need to store a pointer to the Method and the program counter.
882f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We have 4-byte pointers, so we use '[I'.
883f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
884f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (wantObject) {
885f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(sizeof(Method*) == 4);
886f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        stackData = dvmAllocPrimitiveArray('I', stackDepth*2, ALLOC_DEFAULT);
887f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (stackData == NULL) {
888f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            assert(dvmCheckException(dvmThreadSelf()));
889f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
890f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
891d5c36b9040bd26a81219a7f399513526f9b46324Carl Shapiro        intPtr = (int*)(void*)stackData->contents;
892f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
893f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* array of ints; first entry is stack depth */
894f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(sizeof(Method*) == sizeof(int));
895f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        simpleData = (int*) malloc(sizeof(int) * stackDepth*2);
896f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (simpleData == NULL)
897f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;
898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
899f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(pCount != NULL);
900f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        intPtr = simpleData;
901f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
902f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (pCount != NULL)
903f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *pCount = stackDepth;
904f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
905f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fp = startFp;
906f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (fp != NULL) {
907f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const StackSaveArea* saveArea = SAVEAREA_FROM_FP(fp);
908f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const Method* method = saveArea->method;
909f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
910fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro        if (!dvmIsBreakFrame((u4*)fp)) {
91160fc806b679a3655c228b4093058c59941a49cfeDan Bornstein            //LOGD("EXCEP keeping %s.%s", method->clazz->descriptor,
912f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //         method->name);
913f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
914f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *intPtr++ = (int) method;
915f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (dvmIsNativeMethod(method)) {
916f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                *intPtr++ = 0;      /* no saved PC for native methods */
917f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
918f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                assert(saveArea->xtra.currentPc >= method->insns &&
919de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro                        saveArea->xtra.currentPc <
920f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        method->insns + dvmGetMethodInsnsSize(method));
921f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                *intPtr++ = (int) (saveArea->xtra.currentPc - method->insns);
922f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
923f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
924f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            stackDepth--;       // for verification
925f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
926f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
927f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert(fp != saveArea->prevFrame);
928f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fp = saveArea->prevFrame;
929f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
930f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(stackDepth == 0);
931f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
932f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
933f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (wantObject) {
934f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmReleaseTrackedAlloc((Object*) stackData, dvmThreadSelf());
935f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return stackData;
936f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
937f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return simpleData;
938f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
939f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
940f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
941f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
942f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
943f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Given an Object previously created by dvmFillInStackTrace(), use the
944f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * contents of the saved stack trace to generate an array of
945f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * java/lang/StackTraceElement objects.
946f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
947f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The returned array is not added to the "local refs" list.
948f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
949f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectArrayObject* dvmGetStackTrace(const Object* ostackData)
950f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
951f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const ArrayObject* stackData = (const ArrayObject*) ostackData;
9526b1f9f877b70fcc5375fa33a445ac84777757eb2Brian Carlstrom    size_t stackSize = stackData->length / 2;
953d5c36b9040bd26a81219a7f399513526f9b46324Carl Shapiro    const int* intVals = (const int*)(void*)stackData->contents;
954f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return dvmGetStackTraceRaw(intVals, stackSize);
955f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
956f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
957f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
958f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Generate an array of StackTraceElement objects from the raw integer
959f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * data encoded by dvmFillInStackTrace().
960f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
961f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "intVals" points to the first {method,pc} pair.
962f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
963f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The returned array is not added to the "local refs" list.
964f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
9656b1f9f877b70fcc5375fa33a445ac84777757eb2Brian CarlstromArrayObject* dvmGetStackTraceRaw(const int* intVals, size_t stackDepth)
966f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
967f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* allocate a StackTraceElement array */
968a4f4a73edf03cd08b5b2d775913bcac674a117bbCarl Shapiro    ClassObject* klass = gDvm.classJavaLangStackTraceElementArray;
969a4f4a73edf03cd08b5b2d775913bcac674a117bbCarl Shapiro    ArrayObject* array = dvmAllocArrayByClass(klass, stackDepth, ALLOC_DEFAULT);
970a4f4a73edf03cd08b5b2d775913bcac674a117bbCarl Shapiro    if (array != NULL){
971a4f4a73edf03cd08b5b2d775913bcac674a117bbCarl Shapiro      dvmFillStackTraceElements(intVals, stackDepth, array);
972a4f4a73edf03cd08b5b2d775913bcac674a117bbCarl Shapiro      dvmReleaseTrackedAlloc((Object*) array, NULL);
973a4f4a73edf03cd08b5b2d775913bcac674a117bbCarl Shapiro    }
974a4f4a73edf03cd08b5b2d775913bcac674a117bbCarl Shapiro    return array;
9756b1f9f877b70fcc5375fa33a445ac84777757eb2Brian Carlstrom}
9766b1f9f877b70fcc5375fa33a445ac84777757eb2Brian Carlstrom
9776b1f9f877b70fcc5375fa33a445ac84777757eb2Brian Carlstrom/*
9786b1f9f877b70fcc5375fa33a445ac84777757eb2Brian Carlstrom * Fills the StackTraceElement array elements from the raw integer
9796b1f9f877b70fcc5375fa33a445ac84777757eb2Brian Carlstrom * data encoded by dvmFillInStackTrace().
9806b1f9f877b70fcc5375fa33a445ac84777757eb2Brian Carlstrom *
9816b1f9f877b70fcc5375fa33a445ac84777757eb2Brian Carlstrom * "intVals" points to the first {method,pc} pair.
9826b1f9f877b70fcc5375fa33a445ac84777757eb2Brian Carlstrom */
9836b1f9f877b70fcc5375fa33a445ac84777757eb2Brian Carlstromvoid dvmFillStackTraceElements(const int* intVals, size_t stackDepth, ArrayObject* steArray)
9846b1f9f877b70fcc5375fa33a445ac84777757eb2Brian Carlstrom{
9856b1f9f877b70fcc5375fa33a445ac84777757eb2Brian Carlstrom    unsigned int i;
9866b1f9f877b70fcc5375fa33a445ac84777757eb2Brian Carlstrom
9876b1f9f877b70fcc5375fa33a445ac84777757eb2Brian Carlstrom    /* init this if we haven't yet */
9886b1f9f877b70fcc5375fa33a445ac84777757eb2Brian Carlstrom    if (!dvmIsClassInitialized(gDvm.classJavaLangStackTraceElement))
9896b1f9f877b70fcc5375fa33a445ac84777757eb2Brian Carlstrom        dvmInitClass(gDvm.classJavaLangStackTraceElement);
9906b1f9f877b70fcc5375fa33a445ac84777757eb2Brian Carlstrom
991f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
992f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Allocate and initialize a StackTraceElement for each stack frame.
993f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * We use the standard constructor to configure the object.
994f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
995f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < stackDepth; i++) {
996f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Object* ste;
997f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Method* meth;
998f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        StringObject* className;
999f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        StringObject* methodName;
1000f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        StringObject* fileName;
1001f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int lineNumber, pc;
1002f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const char* sourceFile;
1003f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char* dotName;
1004f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1005f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ste = dvmAllocObject(gDvm.classJavaLangStackTraceElement,ALLOC_DEFAULT);
1006f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (ste == NULL)
10076b1f9f877b70fcc5375fa33a445ac84777757eb2Brian Carlstrom            return;
1008f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1009f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        meth = (Method*) *intVals++;
1010f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pc = *intVals++;
1011f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1012f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pc == -1)      // broken top frame?
1013f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            lineNumber = 0;
1014f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        else
1015f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            lineNumber = dvmLineNumFromPC(meth, pc);
1016f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
10175016966b91f1bc36b2bd52ec13ecfd8de1c68209Elliott Hughes        dotName = dvmHumanReadableDescriptor(meth->clazz->descriptor);
101881f3ebe03cd33c9003641084bece0604ee68bf88Barry Hayes        className = dvmCreateStringFromCstr(dotName);
1019f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        free(dotName);
1020f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
102181f3ebe03cd33c9003641084bece0604ee68bf88Barry Hayes        methodName = dvmCreateStringFromCstr(meth->name);
1022f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sourceFile = dvmGetMethodSourceFile(meth);
1023f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (sourceFile != NULL)
102481f3ebe03cd33c9003641084bece0604ee68bf88Barry Hayes            fileName = dvmCreateStringFromCstr(sourceFile);
1025f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        else
1026f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            fileName = NULL;
1027f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1028f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
1029f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Invoke:
1030f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *  public StackTraceElement(String declaringClass, String methodName,
1031f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *      String fileName, int lineNumber)
1032f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * (where lineNumber==-2 means "native")
1033f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
1034f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        JValue unused;
1035f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmCallMethod(dvmThreadSelf(), gDvm.methJavaLangStackTraceElement_init,
1036f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ste, &unused, className, methodName, fileName, lineNumber);
1037f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1038f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmReleaseTrackedAlloc(ste, NULL);
1039f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmReleaseTrackedAlloc((Object*) className, NULL);
1040f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmReleaseTrackedAlloc((Object*) methodName, NULL);
1041f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmReleaseTrackedAlloc((Object*) fileName, NULL);
1042f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1043f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (dvmCheckException(dvmThreadSelf()))
10446b1f9f877b70fcc5375fa33a445ac84777757eb2Brian Carlstrom            return;
1045f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1046364f9d924cbd9d392744a66f80cc084c3d80caf0Barry Hayes        dvmSetObjectArrayElement(steArray, i, ste);
1047f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1048f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1049f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1050f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1051f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump the contents of a raw stack trace to the log.
1052f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1053f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmLogRawStackTrace(const int* intVals, int stackDepth)
1054f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1055f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i;
1056f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1057f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
1058f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Run through the array of stack frame data.
1059f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1060f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = 0; i < stackDepth; i++) {
1061f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Method* meth;
1062f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int lineNumber, pc;
1063f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const char* sourceFile;
1064f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char* dotName;
1065f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1066f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        meth = (Method*) *intVals++;
1067f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pc = *intVals++;
1068f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1069f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pc == -1)      // broken top frame?
1070f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            lineNumber = 0;
1071f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        else
1072f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            lineNumber = dvmLineNumFromPC(meth, pc);
1073f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1074f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // probably don't need to do this, but it looks nicer
10755016966b91f1bc36b2bd52ec13ecfd8de1c68209Elliott Hughes        dotName = dvmHumanReadableDescriptor(meth->clazz->descriptor);
1076f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1077f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (dvmIsNativeMethod(meth)) {
107860fc806b679a3655c228b4093058c59941a49cfeDan Bornstein            LOGI("\tat %s.%s(Native Method)", dotName, meth->name);
1079f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
108060fc806b679a3655c228b4093058c59941a49cfeDan Bornstein            LOGI("\tat %s.%s(%s:%d)",
1081f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dotName, meth->name, dvmGetMethodSourceFile(meth),
1082f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                dvmLineNumFromPC(meth, pc));
1083f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
1084f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1085f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        free(dotName);
1086f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1087f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sourceFile = dvmGetMethodSourceFile(meth);
1088f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1089f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1090f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1091f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
10928552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden * Get the message string.  We'd like to just grab the field out of
10938552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden * Throwable, but the getMessage() function can be overridden by the
10948552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden * sub-class.
10958552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden *
10968552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden * Returns the message string object, or NULL if it wasn't set or
10978552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden * we encountered a failure trying to retrieve it.  The string will
10988552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden * be added to the tracked references table.
10998552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden */
11008552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFaddenstatic StringObject* getExceptionMessage(Object* exception)
11018552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden{
11028552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden    Thread* self = dvmThreadSelf();
11038552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden    Method* getMessageMethod;
11048552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden    StringObject* messageStr = NULL;
11058cd640b8327e2591c8dd8a69093fa1fc6c901c05Andy McFadden    Object* pendingException;
11068552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden
11078cd640b8327e2591c8dd8a69093fa1fc6c901c05Andy McFadden    /*
11088cd640b8327e2591c8dd8a69093fa1fc6c901c05Andy McFadden     * If an exception is pending, clear it while we work and restore
11098cd640b8327e2591c8dd8a69093fa1fc6c901c05Andy McFadden     * it when we're done.
11108cd640b8327e2591c8dd8a69093fa1fc6c901c05Andy McFadden     */
11118cd640b8327e2591c8dd8a69093fa1fc6c901c05Andy McFadden    pendingException = dvmGetException(self);
11128cd640b8327e2591c8dd8a69093fa1fc6c901c05Andy McFadden    if (pendingException != NULL) {
11138cd640b8327e2591c8dd8a69093fa1fc6c901c05Andy McFadden        dvmAddTrackedAlloc(pendingException, self);
11148cd640b8327e2591c8dd8a69093fa1fc6c901c05Andy McFadden        dvmClearException(self);
11158cd640b8327e2591c8dd8a69093fa1fc6c901c05Andy McFadden    }
11168552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden
11178552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden    getMessageMethod = dvmFindVirtualMethodHierByDescriptor(exception->clazz,
11188552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden            "getMessage", "()Ljava/lang/String;");
11198552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden    if (getMessageMethod != NULL) {
11208552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden        /* could be in NATIVE mode from CheckJNI, so switch state */
11218552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden        ThreadStatus oldStatus = dvmChangeStatus(self, THREAD_RUNNING);
11228552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden        JValue result;
11238552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden
11248552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden        dvmCallMethod(self, getMessageMethod, exception, &result);
11258552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden        messageStr = (StringObject*) result.l;
1126bd74b4b51f16e200854e41bbbe5ee6afb3af4cffAndy McFadden        if (messageStr != NULL)
1127bd74b4b51f16e200854e41bbbe5ee6afb3af4cffAndy McFadden            dvmAddTrackedAlloc((Object*) messageStr, self);
11288552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden
11298552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden        dvmChangeStatus(self, oldStatus);
11308552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden    } else {
113160fc806b679a3655c228b4093058c59941a49cfeDan Bornstein        LOGW("WARNING: could not find getMessage in %s",
11328552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden            exception->clazz->descriptor);
11338552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden    }
11348552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden
11358cd640b8327e2591c8dd8a69093fa1fc6c901c05Andy McFadden    if (dvmGetException(self) != NULL) {
113660fc806b679a3655c228b4093058c59941a49cfeDan Bornstein        LOGW("NOTE: exception thrown while retrieving exception message: %s",
11378cd640b8327e2591c8dd8a69093fa1fc6c901c05Andy McFadden            dvmGetException(self)->clazz->descriptor);
11388cd640b8327e2591c8dd8a69093fa1fc6c901c05Andy McFadden        /* will be overwritten below */
11398552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden    }
11408552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden
11418cd640b8327e2591c8dd8a69093fa1fc6c901c05Andy McFadden    dvmSetException(self, pendingException);
11428cd640b8327e2591c8dd8a69093fa1fc6c901c05Andy McFadden    if (pendingException != NULL) {
11438cd640b8327e2591c8dd8a69093fa1fc6c901c05Andy McFadden        dvmReleaseTrackedAlloc(pendingException, self);
11448cd640b8327e2591c8dd8a69093fa1fc6c901c05Andy McFadden    }
11458552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden    return messageStr;
11468552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden}
11478552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden
11488552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden/*
1149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Print the direct stack trace of the given exception to the log.
1150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void logStackTraceOf(Object* exception)
1152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const ArrayObject* stackData;
1154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    StringObject* messageStr;
1155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int stackSize;
1156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const int* intVals;
1157de952db74f54108630a3dd24af0b38e583b62ed3Andy McFadden    char* className;
1158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
11595016966b91f1bc36b2bd52ec13ecfd8de1c68209Elliott Hughes    className = dvmHumanReadableDescriptor(exception->clazz->descriptor);
11608552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden    messageStr = getExceptionMessage(exception);
1161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (messageStr != NULL) {
1162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char* cp = dvmCreateCstrFromString(messageStr);
11638552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden        dvmReleaseTrackedAlloc((Object*) messageStr, dvmThreadSelf());
11648552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden        messageStr = NULL;
11658552f4498a720a6fcb34ebab69d6e3c34bee491dAndy McFadden
116660fc806b679a3655c228b4093058c59941a49cfeDan Bornstein        LOGI("%s: %s", className, cp);
1167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        free(cp);
1168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
116960fc806b679a3655c228b4093058c59941a49cfeDan Bornstein        LOGI("%s:", className);
1170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1171de952db74f54108630a3dd24af0b38e583b62ed3Andy McFadden    free(className);
1172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1173de952db74f54108630a3dd24af0b38e583b62ed3Andy McFadden    /*
1174de952db74f54108630a3dd24af0b38e583b62ed3Andy McFadden     * This relies on the stackState field, which contains the "raw"
1175de952db74f54108630a3dd24af0b38e583b62ed3Andy McFadden     * form of the stack.  The Throwable class may clear this field
1176de952db74f54108630a3dd24af0b38e583b62ed3Andy McFadden     * after it generates the "cooked" form, in which case we'll have
1177de952db74f54108630a3dd24af0b38e583b62ed3Andy McFadden     * nothing to show.
1178de952db74f54108630a3dd24af0b38e583b62ed3Andy McFadden     */
1179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    stackData = (const ArrayObject*) dvmGetFieldObject(exception,
1180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    gDvm.offJavaLangThrowable_stackState);
1181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (stackData == NULL) {
118260fc806b679a3655c228b4093058c59941a49cfeDan Bornstein        LOGI("  (raw stack trace not found)");
1183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
1184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    stackSize = stackData->length / 2;
1187d5c36b9040bd26a81219a7f399513526f9b46324Carl Shapiro    intVals = (const int*)(void*)stackData->contents;
1188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLogRawStackTrace(intVals, stackSize);
1190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
1191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
1193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Print the stack trace of the current thread's exception, as well as
1194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the stack traces of any chained exceptions, to the log. We extract
1195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the stored stack trace and process it internally instead of calling
1196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * interpreted code.
1197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
11981e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirovoid dvmLogExceptionStackTrace()
1199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
1200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object* exception = dvmThreadSelf()->exception;
1201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    Object* cause;
1202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (exception == NULL) {
120460fc806b679a3655c228b4093058c59941a49cfeDan Bornstein        LOGW("tried to log a null exception?");
1205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
1206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (;;) {
1209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        logStackTraceOf(exception);
1210686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden        cause = dvmGetExceptionCause(exception);
1211686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden        if (cause == NULL) {
1212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            break;
1213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
121460fc806b679a3655c228b4093058c59941a49cfeDan Bornstein        LOGI("Caused by:");
1215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        exception = cause;
1216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
1217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
12180016024cdd2bdeef3b98c92f7a8f40a2bc1ff42dElliott Hughes
121961f4c7e40b885ccb0a55d9553f07a888469621dcDan Bornstein/*
122061f4c7e40b885ccb0a55d9553f07a888469621dcDan Bornstein * Helper for a few of the throw functions defined below. This throws
122161f4c7e40b885ccb0a55d9553f07a888469621dcDan Bornstein * the indicated exception, with a message based on a format in which
122261f4c7e40b885ccb0a55d9553f07a888469621dcDan Bornstein * "%s" is used exactly twice, first for a received class and second
122361f4c7e40b885ccb0a55d9553f07a888469621dcDan Bornstein * for the expected class.
122461f4c7e40b885ccb0a55d9553f07a888469621dcDan Bornstein */
122561f4c7e40b885ccb0a55d9553f07a888469621dcDan Bornsteinstatic void throwTypeError(ClassObject* exceptionClass, const char* fmt,
122661f4c7e40b885ccb0a55d9553f07a888469621dcDan Bornstein    ClassObject* actual, ClassObject* desired)
122761f4c7e40b885ccb0a55d9553f07a888469621dcDan Bornstein{
122861f4c7e40b885ccb0a55d9553f07a888469621dcDan Bornstein    char* actualClassName = dvmHumanReadableDescriptor(actual->descriptor);
122961f4c7e40b885ccb0a55d9553f07a888469621dcDan Bornstein    char* desiredClassName = dvmHumanReadableDescriptor(desired->descriptor);
123061f4c7e40b885ccb0a55d9553f07a888469621dcDan Bornstein    dvmThrowExceptionFmt(exceptionClass, fmt,
123161f4c7e40b885ccb0a55d9553f07a888469621dcDan Bornstein        actualClassName, desiredClassName);
123261f4c7e40b885ccb0a55d9553f07a888469621dcDan Bornstein    free(desiredClassName);
123361f4c7e40b885ccb0a55d9553f07a888469621dcDan Bornstein    free(actualClassName);
123461f4c7e40b885ccb0a55d9553f07a888469621dcDan Bornstein}
123561f4c7e40b885ccb0a55d9553f07a888469621dcDan Bornstein
1236d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowAbstractMethodError(const char* msg) {
12370b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornstein    dvmThrowException(gDvm.exAbstractMethodError, msg);
1238d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1239d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
1240d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowArithmeticException(const char* msg) {
12410b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornstein    dvmThrowException(gDvm.exArithmeticException, msg);
1242d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1243d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
124447f58250c5177adba475b0b11a36151ac0ce9ab9Dan Bornsteinvoid dvmThrowArrayIndexOutOfBoundsException(int length, int index)
124574501e600dcb5634aa26aee0a3f57f2b45b213f2Dan Bornstein{
12460b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornstein    dvmThrowExceptionFmt(gDvm.exArrayIndexOutOfBoundsException,
12479b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein        "length=%d; index=%d", length, index);
124874501e600dcb5634aa26aee0a3f57f2b45b213f2Dan Bornstein}
124974501e600dcb5634aa26aee0a3f57f2b45b213f2Dan Bornstein
125061f4c7e40b885ccb0a55d9553f07a888469621dcDan Bornsteinvoid dvmThrowArrayStoreExceptionIncompatibleElement(ClassObject* objectType,
125161f4c7e40b885ccb0a55d9553f07a888469621dcDan Bornstein        ClassObject* arrayType)
125261f4c7e40b885ccb0a55d9553f07a888469621dcDan Bornstein{
125361f4c7e40b885ccb0a55d9553f07a888469621dcDan Bornstein    throwTypeError(gDvm.exArrayStoreException,
125461f4c7e40b885ccb0a55d9553f07a888469621dcDan Bornstein        "%s cannot be stored in an array of type %s",
125561f4c7e40b885ccb0a55d9553f07a888469621dcDan Bornstein        objectType, arrayType);
125661f4c7e40b885ccb0a55d9553f07a888469621dcDan Bornstein}
125761f4c7e40b885ccb0a55d9553f07a888469621dcDan Bornstein
125861f4c7e40b885ccb0a55d9553f07a888469621dcDan Bornsteinvoid dvmThrowArrayStoreExceptionNotArray(ClassObject* actual, const char* label)
1259c560e30f68265068bed9eadf174d1e76288d2952Elliott Hughes{
12605016966b91f1bc36b2bd52ec13ecfd8de1c68209Elliott Hughes    char* actualClassName = dvmHumanReadableDescriptor(actual->descriptor);
126161f4c7e40b885ccb0a55d9553f07a888469621dcDan Bornstein    dvmThrowExceptionFmt(gDvm.exArrayStoreException,
126261f4c7e40b885ccb0a55d9553f07a888469621dcDan Bornstein            "%s of type %s is not an array",
126361f4c7e40b885ccb0a55d9553f07a888469621dcDan Bornstein            label, actualClassName);
1264c560e30f68265068bed9eadf174d1e76288d2952Elliott Hughes    free(actualClassName);
1265c560e30f68265068bed9eadf174d1e76288d2952Elliott Hughes}
126663644657f74e0a5d05f2c5fb56a18872e7ac7427Elliott Hughes
126761f4c7e40b885ccb0a55d9553f07a888469621dcDan Bornsteinvoid dvmThrowArrayStoreExceptionIncompatibleArrays(ClassObject* source, ClassObject* destination)
126863644657f74e0a5d05f2c5fb56a18872e7ac7427Elliott Hughes{
12696d167a4b02f310700a55fc9a24fccce999e0fdf2Dan Bornstein    throwTypeError(gDvm.exArrayStoreException,
127061f4c7e40b885ccb0a55d9553f07a888469621dcDan Bornstein        "%s and %s are incompatible array types",
127161f4c7e40b885ccb0a55d9553f07a888469621dcDan Bornstein        source, destination);
127261f4c7e40b885ccb0a55d9553f07a888469621dcDan Bornstein}
127361f4c7e40b885ccb0a55d9553f07a888469621dcDan Bornstein
127461f4c7e40b885ccb0a55d9553f07a888469621dcDan Bornsteinvoid dvmThrowArrayStoreExceptionIncompatibleArrayElement(s4 index, ClassObject* objectType,
127561f4c7e40b885ccb0a55d9553f07a888469621dcDan Bornstein        ClassObject* arrayType)
127661f4c7e40b885ccb0a55d9553f07a888469621dcDan Bornstein{
127761f4c7e40b885ccb0a55d9553f07a888469621dcDan Bornstein    char* objectClassName = dvmHumanReadableDescriptor(objectType->descriptor);
127861f4c7e40b885ccb0a55d9553f07a888469621dcDan Bornstein    char* arrayClassName = dvmHumanReadableDescriptor(arrayType->descriptor);
127961f4c7e40b885ccb0a55d9553f07a888469621dcDan Bornstein    dvmThrowExceptionFmt(gDvm.exArrayStoreException,
128061f4c7e40b885ccb0a55d9553f07a888469621dcDan Bornstein        "source[%d] of type %s cannot be stored in destination array of type %s",
128161f4c7e40b885ccb0a55d9553f07a888469621dcDan Bornstein        index, objectClassName, arrayClassName);
128261f4c7e40b885ccb0a55d9553f07a888469621dcDan Bornstein    free(objectClassName);
128361f4c7e40b885ccb0a55d9553f07a888469621dcDan Bornstein    free(arrayClassName);
128463644657f74e0a5d05f2c5fb56a18872e7ac7427Elliott Hughes}
128563644657f74e0a5d05f2c5fb56a18872e7ac7427Elliott Hughes
128663644657f74e0a5d05f2c5fb56a18872e7ac7427Elliott Hughesvoid dvmThrowClassCastException(ClassObject* actual, ClassObject* desired)
128763644657f74e0a5d05f2c5fb56a18872e7ac7427Elliott Hughes{
12886d167a4b02f310700a55fc9a24fccce999e0fdf2Dan Bornstein    throwTypeError(gDvm.exClassCastException,
128963644657f74e0a5d05f2c5fb56a18872e7ac7427Elliott Hughes        "%s cannot be cast to %s", actual, desired);
129063644657f74e0a5d05f2c5fb56a18872e7ac7427Elliott Hughes}
1291d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
129270b00abc45d7d04342a96a03749f993028b060f7Dan Bornsteinvoid dvmThrowClassCircularityError(const char* descriptor) {
12930b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornstein    dvmThrowExceptionWithClassMessage(gDvm.exClassCircularityError,
129470b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein            descriptor);
129570b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein}
129670b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein
129770b00abc45d7d04342a96a03749f993028b060f7Dan Bornsteinvoid dvmThrowClassFormatError(const char* msg) {
12980b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornstein    dvmThrowException(gDvm.exClassFormatError, msg);
129970b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein}
130070b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein
13019b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornsteinvoid dvmThrowClassNotFoundException(const char* name) {
1302f39ec04426f497114e237b93effea30bdcf295edDan Bornstein    dvmThrowChainedClassNotFoundException(name, NULL);
13039b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein}
13049b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein
13059b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornsteinvoid dvmThrowChainedClassNotFoundException(const char* name, Object* cause) {
1306f39ec04426f497114e237b93effea30bdcf295edDan Bornstein    /*
1307f39ec04426f497114e237b93effea30bdcf295edDan Bornstein     * Note: This exception is thrown in response to a request coming
1308f39ec04426f497114e237b93effea30bdcf295edDan Bornstein     * from client code for the name as given, so it is preferable to
1309f39ec04426f497114e237b93effea30bdcf295edDan Bornstein     * make the exception message be that string, per se, instead of
1310f39ec04426f497114e237b93effea30bdcf295edDan Bornstein     * trying to prettify it.
1311f39ec04426f497114e237b93effea30bdcf295edDan Bornstein     */
1312f39ec04426f497114e237b93effea30bdcf295edDan Bornstein    dvmThrowChainedException(gDvm.exClassNotFoundException, name, cause);
13139b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein}
13149b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein
13151e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirovoid dvmThrowExceptionInInitializerError()
13169b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein{
13179b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein    /*
13189b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein     * TODO: Do we want to wrap it if the original is an Error rather than
13199b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein     * an Exception?
13209b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein     *
13219b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein     * TODO: Should this just use dvmWrapException()?
13229b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein     */
13239b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein
13249b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein    if (gDvm.exExceptionInInitializerError == NULL) {
13259b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein        /*
13269b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein         * ExceptionInInitializerError isn't itself initialized. This
13279b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein         * can happen very early during VM startup if there is a
13289b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein         * problem with one of the corest-of-the-core classes, and it
13299b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein         * can possibly happen during a dexopt run. Rather than do
13309b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein         * anything fancier, we just abort here with a blatant
13319b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein         * message.
13329b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein         */
133360fc806b679a3655c228b4093058c59941a49cfeDan Bornstein        LOGE("Fatal error during early class initialization:");
13349b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein        dvmLogExceptionStackTrace();
13359b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein        dvmAbort();
13369b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein    }
13379b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein
13389b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein    Thread* self = dvmThreadSelf();
13399b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein    Object* exception = dvmGetException(self);
13409b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein
13419b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein    dvmAddTrackedAlloc(exception, self);
13429b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein    dvmClearException(self);
13439b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein
13440b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornstein    dvmThrowChainedException(gDvm.exExceptionInInitializerError,
13459b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein            NULL, exception);
13469b598e34e2401bda77fca9c8f3a5c50e882e6d68Dan Bornstein    dvmReleaseTrackedAlloc(exception, self);
1347d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1348d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
1349d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowFileNotFoundException(const char* msg) {
13500b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornstein    dvmThrowException(gDvm.exFileNotFoundException, msg);
1351d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1352d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
1353d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowIOException(const char* msg) {
13540b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornstein    dvmThrowException(gDvm.exIOException, msg);
1355d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1356d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
1357d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowIllegalAccessException(const char* msg) {
13580b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornstein    dvmThrowException(gDvm.exIllegalAccessException, msg);
1359d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1360d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
1361d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowIllegalAccessError(const char* msg) {
13620b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornstein    dvmThrowException(gDvm.exIllegalAccessError, msg);
1363d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1364d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
1365d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowIllegalArgumentException(const char* msg) {
13660b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornstein    dvmThrowException(gDvm.exIllegalArgumentException, msg);
1367d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1368d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
1369d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowIllegalMonitorStateException(const char* msg) {
13700b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornstein    dvmThrowException(gDvm.exIllegalMonitorStateException, msg);
1371d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1372d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
1373d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowIllegalStateException(const char* msg) {
13740b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornstein    dvmThrowException(gDvm.exIllegalStateException, msg);
1375d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1376d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
1377d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowIllegalThreadStateException(const char* msg) {
13780b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornstein    dvmThrowException(gDvm.exIllegalThreadStateException, msg);
1379d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1380d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
138170b00abc45d7d04342a96a03749f993028b060f7Dan Bornsteinvoid dvmThrowIncompatibleClassChangeError(const char* msg) {
13820b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornstein    dvmThrowException(gDvm.exIncompatibleClassChangeError, msg);
138370b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein}
138470b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein
138570b00abc45d7d04342a96a03749f993028b060f7Dan Bornsteinvoid dvmThrowIncompatibleClassChangeErrorWithClassMessage(
138670b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein        const char* descriptor)
138770b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein{
13880b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornstein    dvmThrowExceptionWithClassMessage(
138985ba81d1da57c9f19c54bee3d7907b70045dad46Dan Bornstein            gDvm.exIncompatibleClassChangeError, descriptor);
139070b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein}
139170b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein
1392bc606f5e72b16f3759f5d414c7444204908718aaDan Bornsteinvoid dvmThrowInstantiationException(ClassObject* clazz,
1393bc606f5e72b16f3759f5d414c7444204908718aaDan Bornstein        const char* extraDetail) {
1394bc606f5e72b16f3759f5d414c7444204908718aaDan Bornstein    char* className = dvmHumanReadableDescriptor(clazz->descriptor);
13950b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornstein    dvmThrowExceptionFmt(gDvm.exInstantiationException,
1396bc606f5e72b16f3759f5d414c7444204908718aaDan Bornstein            "can't instantiate class %s%s%s", className,
1397bc606f5e72b16f3759f5d414c7444204908718aaDan Bornstein            (extraDetail == NULL) ? "" : "; ",
1398bc606f5e72b16f3759f5d414c7444204908718aaDan Bornstein            (extraDetail == NULL) ? "" : extraDetail);
1399bc606f5e72b16f3759f5d414c7444204908718aaDan Bornstein    free(className);
1400bc606f5e72b16f3759f5d414c7444204908718aaDan Bornstein}
1401bc606f5e72b16f3759f5d414c7444204908718aaDan Bornstein
1402d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowInternalError(const char* msg) {
14030b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornstein    dvmThrowException(gDvm.exInternalError, msg);
1404d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1405d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
1406d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowInterruptedException(const char* msg) {
14070b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornstein    dvmThrowException(gDvm.exInterruptedException, msg);
1408d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1409d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
141070b00abc45d7d04342a96a03749f993028b060f7Dan Bornsteinvoid dvmThrowLinkageError(const char* msg) {
14110b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornstein    dvmThrowException(gDvm.exLinkageError, msg);
141270b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein}
141370b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein
14142c8e25b2010d1bba4dca0148691bc6e1a4ee7616Dan Bornsteinvoid dvmThrowNegativeArraySizeException(s4 size) {
14150b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornstein    dvmThrowExceptionFmt(gDvm.exNegativeArraySizeException, "%d", size);
1416d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1417d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
1418d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowNoClassDefFoundError(const char* descriptor) {
14190b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornstein    dvmThrowExceptionWithClassMessage(gDvm.exNoClassDefFoundError,
1420d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein            descriptor);
1421d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1422d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
1423a3b3512e99ef51940b0a13e57528bd32803f72b4Dan Bornsteinvoid dvmThrowChainedNoClassDefFoundError(const char* descriptor,
1424a3b3512e99ef51940b0a13e57528bd32803f72b4Dan Bornstein        Object* cause) {
14250b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornstein    dvmThrowChainedExceptionWithClassMessage(
1426a3b3512e99ef51940b0a13e57528bd32803f72b4Dan Bornstein            gDvm.exNoClassDefFoundError, descriptor, cause);
1427a3b3512e99ef51940b0a13e57528bd32803f72b4Dan Bornstein}
1428a3b3512e99ef51940b0a13e57528bd32803f72b4Dan Bornstein
1429d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowNoSuchFieldError(const char* msg) {
14300b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornstein    dvmThrowException(gDvm.exNoSuchFieldError, msg);
1431d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1432d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
1433d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowNoSuchFieldException(const char* msg) {
14340b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornstein    dvmThrowException(gDvm.exNoSuchFieldException, msg);
1435d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1436d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
1437d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowNoSuchMethodError(const char* msg) {
14380b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornstein    dvmThrowException(gDvm.exNoSuchMethodError, msg);
1439d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1440d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
1441d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowNullPointerException(const char* msg) {
14420b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornstein    dvmThrowException(gDvm.exNullPointerException, msg);
1443d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1444d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
1445d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowOutOfMemoryError(const char* msg) {
14460b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornstein    dvmThrowException(gDvm.exOutOfMemoryError, msg);
1447d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1448d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
1449d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowRuntimeException(const char* msg) {
14500b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornstein    dvmThrowException(gDvm.exRuntimeException, msg);
1451d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1452d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
145374501e600dcb5634aa26aee0a3f57f2b45b213f2Dan Bornsteinvoid dvmThrowStaleDexCacheError(const char* msg) {
14540b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornstein    dvmThrowException(gDvm.exStaleDexCacheError, msg);
145574501e600dcb5634aa26aee0a3f57f2b45b213f2Dan Bornstein}
145674501e600dcb5634aa26aee0a3f57f2b45b213f2Dan Bornstein
14577a86c44bde10b37d8df17d0613072c4ef134189cDan Bornsteinvoid dvmThrowStringIndexOutOfBoundsExceptionWithIndex(jsize stringLength,
14587a86c44bde10b37d8df17d0613072c4ef134189cDan Bornstein        jsize requestIndex) {
14590b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornstein    dvmThrowExceptionFmt(gDvm.exStringIndexOutOfBoundsException,
146039f8af436c68c5ddfaf79f6f0372f535e2a52651Dan Bornstein            "length=%d; index=%d", stringLength, requestIndex);
14617a86c44bde10b37d8df17d0613072c4ef134189cDan Bornstein}
14627a86c44bde10b37d8df17d0613072c4ef134189cDan Bornstein
14637a86c44bde10b37d8df17d0613072c4ef134189cDan Bornsteinvoid dvmThrowStringIndexOutOfBoundsExceptionWithRegion(jsize stringLength,
14647a86c44bde10b37d8df17d0613072c4ef134189cDan Bornstein        jsize requestStart, jsize requestLength) {
14650b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornstein    dvmThrowExceptionFmt(gDvm.exStringIndexOutOfBoundsException,
146647f58250c5177adba475b0b11a36151ac0ce9ab9Dan Bornstein            "length=%d; regionStart=%d; regionLength=%d",
14677a86c44bde10b37d8df17d0613072c4ef134189cDan Bornstein            stringLength, requestStart, requestLength);
1468d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
1469d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein
147085ba81d1da57c9f19c54bee3d7907b70045dad46Dan Bornsteinvoid dvmThrowTypeNotPresentException(const char* descriptor) {
14710b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornstein    dvmThrowExceptionWithClassMessage(gDvm.exTypeNotPresentException,
147285ba81d1da57c9f19c54bee3d7907b70045dad46Dan Bornstein            descriptor);
147385ba81d1da57c9f19c54bee3d7907b70045dad46Dan Bornstein}
147485ba81d1da57c9f19c54bee3d7907b70045dad46Dan Bornstein
147570b00abc45d7d04342a96a03749f993028b060f7Dan Bornsteinvoid dvmThrowUnsatisfiedLinkError(const char* msg) {
14760b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornstein    dvmThrowException(gDvm.exUnsatisfiedLinkError, msg);
147770b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein}
147870b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein
1479d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornsteinvoid dvmThrowUnsupportedOperationException(const char* msg) {
14800b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornstein    dvmThrowException(gDvm.exUnsupportedOperationException, msg);
1481d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein}
148270b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein
148385ba81d1da57c9f19c54bee3d7907b70045dad46Dan Bornsteinvoid dvmThrowVerifyError(const char* descriptor) {
14840b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornstein    dvmThrowExceptionWithClassMessage(gDvm.exVerifyError, descriptor);
148585ba81d1da57c9f19c54bee3d7907b70045dad46Dan Bornstein}
148685ba81d1da57c9f19c54bee3d7907b70045dad46Dan Bornstein
148770b00abc45d7d04342a96a03749f993028b060f7Dan Bornsteinvoid dvmThrowVirtualMachineError(const char* msg) {
14880b8b293f228b3d341054bc1fad8a92d6e533b4ddDan Bornstein    dvmThrowException(gDvm.exVirtualMachineError, msg);
148970b00abc45d7d04342a96a03749f993028b060f7Dan Bornstein}
1490