Exception.cpp revision 0171812e59e2520a4345b9bbadd4f7afa0a1de16
1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License. 6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at 7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and 14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License. 15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Exception handling. 18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "Dalvik.h" 20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "libdex/DexCatch.h" 21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <stdlib.h> 23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectNotes on Exception Handling 26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectWe have one fairly sticky issue to deal with: creating the exception stack 28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecttrace. The trouble is that we need the current value of the program 29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectcounter for the method now being executed, but that's only held in a local 30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvariable or hardware register in the main interpreter loop. 31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectThe exception mechanism requires that the current stack trace be associated 33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectwith a Throwable at the time the Throwable is constructed. The construction 34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectmay or may not be associated with a throw. We have three situations to 35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectconsider: 36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (1) A Throwable is created with a "new Throwable" statement in the 38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project application code, for immediate or deferred use with a "throw" statement. 39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (2) The VM throws an exception from within the interpreter core, e.g. 40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project after an integer divide-by-zero. 41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (3) The VM throws an exception from somewhere deeper down, e.g. while 42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project trying to link a class. 43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectWe need to have the current value for the PC, which means that for 45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectsituation (3) the interpreter loop must copy it to an externally-accessible 46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectlocation before handling any opcode that could cause the VM to throw 47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectan exception. We can't store it globally, because the various threads 48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectwould trample each other. We can't store it in the Thread structure, 49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbecause it'll get overwritten as soon as the Throwable constructor starts 50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectexecuting. It needs to go on the stack, but our stack frames hold the 51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectcaller's *saved* PC, not the current PC. 52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectSituation #1 doesn't require special handling. Situation #2 could be dealt 54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectwith by passing the PC into the exception creation function. The trick 55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectis to solve situation #3 in a way that adds minimal overhead to common 56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectoperations. Making it more costly to throw an exception is acceptable. 57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectThere are a few ways to deal with this: 59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (a) Change "savedPc" to "currentPc" in the stack frame. All of the 61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stack logic gets offset by one frame. The current PC is written 62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project to the current stack frame when necessary. 63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (b) Write the current PC into the current stack frame, but without 64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project replacing "savedPc". The JNI local refs pointer, which is only 65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project used for native code, can be overloaded to save space. 66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (c) In dvmThrowException(), push an extra stack frame on, with the 67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project current PC in it. The current PC is written into the Thread struct 68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project when necessary, and copied out when the VM throws. 69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (d) Before doing something that might throw an exception, push a 70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project temporary frame on with the saved PC in it. 71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectSolution (a) is the simplest, but breaks Dalvik's goal of mingling native 73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectand interpreted stacks. 74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectSolution (b) retains the simplicity of (a) without rearranging the stack, 76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbut now in some cases we're storing the PC twice, which feels wrong. 77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectSolution (c) usually works, because we push the saved PC onto the stack 79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbefore the Throwable construction can overwrite the copy in Thread. One 80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectway solution (c) could break is: 81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project - Interpreter saves the PC 82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project - Execute some bytecode, which runs successfully (and alters the saved PC) 83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project - Throw an exception before re-saving the PC (i.e in the same opcode) 84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectThis is a risk for anything that could cause <clinit> to execute, e.g. 85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectexecuting a static method or accessing a static field. Attemping to access 86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projecta field that doesn't exist in a class that does exist might cause this. 87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectIt may be possible to simply bracket the dvmCallMethod*() functions to 88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectsave/restore it. 89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectSolution (d) incurs additional overhead, but may have other benefits (e.g. 91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectit's easy to find the stack frames that should be removed before storage 92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectin the Throwable). 93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectCurrent plan is option (b), because it's simple, fast, and doesn't change 95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectthe way the stack works. 96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project*/ 97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* fwd */ 99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool initException(Object* exception, const char* msg, Object* cause, 100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Thread* self); 101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Cache pointers to some of the exception classes we use locally. 105686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden * 106686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden * Note this is NOT called during dexopt optimization. Some of the fields 107686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden * are initialized by the verifier (dvmVerifyCodeFlow). 108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmExceptionStartup(void) 110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gDvm.classJavaLangThrowable = 112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmFindSystemClassNoInit("Ljava/lang/Throwable;"); 113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gDvm.classJavaLangRuntimeException = 114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmFindSystemClassNoInit("Ljava/lang/RuntimeException;"); 115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gDvm.classJavaLangError = 116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmFindSystemClassNoInit("Ljava/lang/Error;"); 117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gDvm.classJavaLangStackTraceElement = 118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmFindSystemClassNoInit("Ljava/lang/StackTraceElement;"); 119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gDvm.classJavaLangStackTraceElementArray = 120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmFindArrayClass("[Ljava/lang/StackTraceElement;", NULL); 121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (gDvm.classJavaLangThrowable == NULL || 122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gDvm.classJavaLangStackTraceElement == NULL || 123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gDvm.classJavaLangStackTraceElementArray == NULL) 124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE("Could not find one or more essential exception classes\n"); 126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Find the constructor. Note that, unlike other saved method lookups, 131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * we're using a Method* instead of a vtable offset. This is because 132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * constructors don't have vtable offsets. (Also, since we're creating 133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the object in question, it's impossible for anyone to sub-class it.) 134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Method* meth; 136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project meth = dvmFindDirectMethodByDescriptor(gDvm.classJavaLangStackTraceElement, 137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "<init>", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V"); 138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (meth == NULL) { 139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE("Unable to find constructor for StackTraceElement\n"); 140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gDvm.methJavaLangStackTraceElement_init = meth; 143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* grab an offset for the stackData field */ 145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gDvm.offJavaLangThrowable_stackState = 146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmFindFieldOffset(gDvm.classJavaLangThrowable, 147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "stackState", "Ljava/lang/Object;"); 148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (gDvm.offJavaLangThrowable_stackState < 0) { 149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE("Unable to find Throwable.stackState\n"); 150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* and one for the message field, in case we want to show it */ 154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gDvm.offJavaLangThrowable_message = 155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmFindFieldOffset(gDvm.classJavaLangThrowable, 156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "detailMessage", "Ljava/lang/String;"); 157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (gDvm.offJavaLangThrowable_message < 0) { 158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE("Unable to find Throwable.detailMessage\n"); 159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* and one for the cause field, just 'cause */ 163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gDvm.offJavaLangThrowable_cause = 164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmFindFieldOffset(gDvm.classJavaLangThrowable, 165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "cause", "Ljava/lang/Throwable;"); 166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (gDvm.offJavaLangThrowable_cause < 0) { 167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE("Unable to find Throwable.cause\n"); 168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Clean up. 176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmExceptionShutdown(void) 178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // nothing to do 180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1840171812e59e2520a4345b9bbadd4f7afa0a1de16Andy McFadden * Format the message into a small buffer and pass it along. 1850171812e59e2520a4345b9bbadd4f7afa0a1de16Andy McFadden */ 1860171812e59e2520a4345b9bbadd4f7afa0a1de16Andy McFaddenvoid dvmThrowExceptionFmtV(const char* exceptionDescriptor, const char* fmt, 1870171812e59e2520a4345b9bbadd4f7afa0a1de16Andy McFadden va_list args) 1880171812e59e2520a4345b9bbadd4f7afa0a1de16Andy McFadden{ 1890171812e59e2520a4345b9bbadd4f7afa0a1de16Andy McFadden char msgBuf[512]; 1900171812e59e2520a4345b9bbadd4f7afa0a1de16Andy McFadden 1910171812e59e2520a4345b9bbadd4f7afa0a1de16Andy McFadden vsnprintf(msgBuf, sizeof(msgBuf), fmt, args); 1920171812e59e2520a4345b9bbadd4f7afa0a1de16Andy McFadden dvmThrowChainedException(exceptionDescriptor, msgBuf, NULL); 1930171812e59e2520a4345b9bbadd4f7afa0a1de16Andy McFadden} 1940171812e59e2520a4345b9bbadd4f7afa0a1de16Andy McFadden 1950171812e59e2520a4345b9bbadd4f7afa0a1de16Andy McFadden/* 196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Create a Throwable and throw an exception in the current thread (where 197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "throwing" just means "set the thread's exception pointer"). 198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "msg" and/or "cause" may be NULL. 200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If we have a bad exception hierarchy -- something in Throwable.<init> 202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * is missing -- then every attempt to throw an exception will result 203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * in another exception. Exceptions are generally allowed to "chain" 204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to other exceptions, so it's hard to auto-detect this problem. It can 205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * only happen if the system classes are broken, so it's probably not 206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * worth spending cycles to detect it. 207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We do have one case to worry about: if the classpath is completely 209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * wrong, we'll go into a death spin during startup because we can't find 210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the initial class and then we can't find NoClassDefFoundError. We have 211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to handle this case. 212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * [Do we want to cache pointers to common exception classes?] 214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmThrowChainedException(const char* exceptionDescriptor, const char* msg, 216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Object* cause) 217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ClassObject* excepClass; 219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGV("THROW '%s' msg='%s' cause=%s\n", 221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project exceptionDescriptor, msg, 222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (cause != NULL) ? cause->clazz->descriptor : "(none)"); 223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (gDvm.initializing) { 225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (++gDvm.initExceptionCount >= 2) { 226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE("Too many exceptions during init (failed on '%s' '%s')\n", 227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project exceptionDescriptor, msg); 228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmAbort(); 229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project excepClass = dvmFindSystemClass(exceptionDescriptor); 233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (excepClass == NULL) { 234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We couldn't find the exception class. The attempt to find a 236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * nonexistent class should have raised an exception. If no 237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * exception is currently raised, then we're pretty clearly unable 238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to throw ANY sort of exception, and we need to pack it in. 239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If we were able to throw the "class load failed" exception, 241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * stick with that. Ideally we'd stuff the original exception 242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * into the "cause" field, but since we can't find it we can't 243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * do that. The exception class name should be in the "message" 244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * field. 245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!dvmCheckException(dvmThreadSelf())) { 247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE("FATAL: unable to throw exception (failed on '%s' '%s')\n", 248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project exceptionDescriptor, msg); 249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmAbort(); 250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmThrowChainedExceptionByClass(excepClass, msg, cause); 255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Start/continue throwing process now that we have a class reference. 259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmThrowChainedExceptionByClass(ClassObject* excepClass, const char* msg, 261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Object* cause) 262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Thread* self = dvmThreadSelf(); 264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Object* exception; 265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* make sure the exception is initialized */ 267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!dvmIsClassInitialized(excepClass) && !dvmInitClass(excepClass)) { 268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE("ERROR: unable to initialize exception class '%s'\n", 269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project excepClass->descriptor); 270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (strcmp(excepClass->descriptor, "Ljava/lang/InternalError;") == 0) 271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmAbort(); 272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmThrowChainedException("Ljava/lang/InternalError;", 273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "failed to init original exception class", cause); 274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project exception = dvmAllocObject(excepClass, ALLOC_DEFAULT); 278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (exception == NULL) { 279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We're in a lot of trouble. We might be in the process of 281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * throwing an out-of-memory exception, in which case the 282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * pre-allocated object will have been thrown when our object alloc 283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * failed. So long as there's an exception raised, return and 284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * allow the system to try to recover. If not, something is broken 285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and we need to bail out. 286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmCheckException(self)) 288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE("FATAL: unable to allocate exception '%s' '%s'\n", 290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project excepClass->descriptor, msg != NULL ? msg : "(no msg)"); 291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmAbort(); 292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Init the exception. 296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (gDvm.optimizing) { 298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* need the exception object, but can't invoke interpreted code */ 299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGV("Skipping init of exception %s '%s'\n", 300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project excepClass->descriptor, msg); 301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(excepClass == exception->clazz); 303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!initException(exception, msg, cause, self)) { 304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Whoops. If we can't initialize the exception, we can't use 306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * it. If there's an exception already set, the constructor 307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * probably threw an OutOfMemoryError. 308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!dvmCheckException(self)) { 310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We're required to throw something, so we just 312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * throw the pre-constructed internal error. 313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->exception = gDvm.internalErrorObj; 315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->exception = exception; 321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail: 323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmReleaseTrackedAlloc(exception, self); 324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Throw the named exception using the dotted form of the class 328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * descriptor as the exception message, and with the specified cause. 329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmThrowChainedExceptionWithClassMessage(const char* exceptionDescriptor, 331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const char* messageDescriptor, Object* cause) 332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project char* message = dvmDescriptorToDot(messageDescriptor); 334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmThrowChainedException(exceptionDescriptor, message, cause); 336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(message); 337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Like dvmThrowExceptionWithMessageFromDescriptor, but take a 341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * class object instead of a name. 342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmThrowExceptionByClassWithClassMessage(ClassObject* exceptionClass, 344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const char* messageDescriptor) 345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project char* message = dvmDescriptorToName(messageDescriptor); 347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmThrowExceptionByClass(exceptionClass, message); 349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(message); 350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 3534a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein * Find and return an exception constructor method that can take the 3544a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein * indicated parameters, or return NULL if no such constructor exists. 3554a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein */ 3564a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornsteinstatic Method* findExceptionInitMethod(ClassObject* excepClass, 3574a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein bool hasMessage, bool hasCause) 3584a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein{ 3594a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein if (hasMessage) { 3604a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein Method* result; 3614a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein 3624a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein if (hasCause) { 3634a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein result = dvmFindDirectMethodByDescriptor( 3644a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein excepClass, "<init>", 3654a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein "(Ljava/lang/String;Ljava/lang/Throwable;)V"); 3664a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein } else { 3674a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein result = dvmFindDirectMethodByDescriptor( 3684a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein excepClass, "<init>", "(Ljava/lang/String;)V"); 3694a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein } 3704a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein 3714a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein if (result != NULL) { 3724a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein return result; 3734a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein } 3744a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein 3754a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein if (hasCause) { 3764a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein return dvmFindDirectMethodByDescriptor( 3774a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein excepClass, "<init>", 3784a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein "(Ljava/lang/Object;Ljava/lang/Throwable;)V"); 3794a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein } else { 3804a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein return dvmFindDirectMethodByDescriptor( 3814a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein excepClass, "<init>", "(Ljava/lang/Object;)V"); 3824a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein } 3834a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein } else if (hasCause) { 3844a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein return dvmFindDirectMethodByDescriptor( 3854a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein excepClass, "<init>", "(Ljava/lang/Throwable;)V"); 3864a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein } else { 3874a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein return dvmFindDirectMethodByDescriptor(excepClass, "<init>", "()V"); 3884a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein } 3894a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein} 3904a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein 3914a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein/* 392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Initialize an exception with an appropriate constructor. 393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "exception" is the exception object to initialize. 395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Either or both of "msg" and "cause" may be null. 396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "self" is dvmThreadSelf(), passed in so we don't have to look it up again. 397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If the process of initializing the exception causes another 399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * exception (e.g., OutOfMemoryError) to be thrown, return an error 400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and leave self->exception intact. 401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool initException(Object* exception, const char* msg, Object* cause, 403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Thread* self) 404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project enum { 406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project kInitUnknown, 407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project kInitNoarg, 408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project kInitMsg, 409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project kInitMsgThrow, 410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project kInitThrow 411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } initKind = kInitUnknown; 412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Method* initMethod = NULL; 413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ClassObject* excepClass = exception->clazz; 414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StringObject* msgStr = NULL; 415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project bool result = false; 416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project bool needInitCause = false; 417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(self != NULL); 419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(self->exception == NULL); 420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* if we have a message, create a String */ 422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (msg == NULL) 423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project msgStr = NULL; 424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else { 425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project msgStr = dvmCreateStringFromCstr(msg, ALLOC_DEFAULT); 426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (msgStr == NULL) { 427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGW("Could not allocate message string \"%s\" while " 428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "throwing internal exception (%s)\n", 429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project msg, excepClass->descriptor); 430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 434686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden if (cause != NULL) { 435686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden if (!dvmInstanceof(cause->clazz, gDvm.classJavaLangThrowable)) { 436686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden LOGE("Tried to init exception with cause '%s'\n", 437686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden cause->clazz->descriptor); 438686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden dvmAbort(); 439686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden } 440686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden } 441686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden 442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The Throwable class has four public constructors: 444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (1) Throwable() 445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (2) Throwable(String message) 446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (3) Throwable(String message, Throwable cause) (added in 1.4) 447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (4) Throwable(Throwable cause) (added in 1.4) 448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The first two are part of the original design, and most exception 450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * classes should support them. The third prototype was used by 451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * individual exceptions. e.g. ClassNotFoundException added it in 1.2. 452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The general "cause" mechanism was added in 1.4. Some classes, 453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * such as IllegalArgumentException, initially supported the first 454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * two, but added the second two in a later release. 455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Exceptions may be picky about how their "cause" field is initialized. 457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If you call ClassNotFoundException(String), it may choose to 458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * initialize its "cause" field to null. Doing so prevents future 459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * calls to Throwable.initCause(). 460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * So, if "cause" is not NULL, we need to look for a constructor that 462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * takes a throwable. If we can't find one, we fall back on calling 463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * #1/#2 and making a separate call to initCause(). Passing a null ref 464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * for "message" into Throwable(String, Throwable) is allowed, but we 465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * prefer to use the Throwable-only version because it has different 466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * behavior. 467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * java.lang.TypeNotPresentException is a strange case -- it has #3 but 469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * not #2. (Some might argue that the constructor is actually not #3, 470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * because it doesn't take the message string as an argument, but it 471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * has the same effect and we can work with it here.) 4724a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein * 4734a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein * java.lang.AssertionError is also a strange case -- it has a 4744a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein * constructor that takes an Object, but not one that takes a String. 4754a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein * There may be other cases like this, as well, so we generally look 4764a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein * for an Object-taking constructor if we can't find one that takes 4774a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein * a String. 478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (cause == NULL) { 480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (msgStr == NULL) { 4814a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein initMethod = findExceptionInitMethod(excepClass, false, false); 482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project initKind = kInitNoarg; 483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 4844a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein initMethod = findExceptionInitMethod(excepClass, true, false); 485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (initMethod != NULL) { 486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project initKind = kInitMsg; 487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* no #2, try #3 */ 4894a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein initMethod = findExceptionInitMethod(excepClass, true, true); 4904a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein if (initMethod != NULL) { 491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project initKind = kInitMsgThrow; 4924a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein } 493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (msgStr == NULL) { 4974a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein initMethod = findExceptionInitMethod(excepClass, false, true); 498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (initMethod != NULL) { 499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project initKind = kInitThrow; 500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 5014a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein initMethod = findExceptionInitMethod(excepClass, false, false); 502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project initKind = kInitNoarg; 503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project needInitCause = true; 504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 5064a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein initMethod = findExceptionInitMethod(excepClass, true, true); 507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (initMethod != NULL) { 508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project initKind = kInitMsgThrow; 509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 5104a888b09be2ade9fc5bb0137f702b3be889679a9Dan Bornstein initMethod = findExceptionInitMethod(excepClass, true, false); 511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project initKind = kInitMsg; 512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project needInitCause = true; 513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (initMethod == NULL) { 518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We can't find the desired constructor. This can happen if a 520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * subclass of java/lang/Throwable doesn't define an expected 521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * constructor, e.g. it doesn't provide one that takes a string 522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * when a message has been provided. 523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGW("WARNING: exception class '%s' missing constructor " 525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "(msg='%s' kind=%d)\n", 526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project excepClass->descriptor, msg, initKind); 527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(strcmp(excepClass->descriptor, 528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "Ljava/lang/RuntimeException;") != 0); 529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmThrowChainedException("Ljava/lang/RuntimeException;", 530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "re-throw on exception class missing constructor", NULL); 531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Call the constructor with the appropriate arguments. 536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project JValue unused; 538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project switch (initKind) { 539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case kInitNoarg: 540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGVV("+++ exc noarg (ic=%d)\n", needInitCause); 541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmCallMethod(self, initMethod, exception, &unused); 542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case kInitMsg: 544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGVV("+++ exc msg (ic=%d)\n", needInitCause); 545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmCallMethod(self, initMethod, exception, &unused, msgStr); 546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case kInitThrow: 548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGVV("+++ exc throw"); 549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(!needInitCause); 550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmCallMethod(self, initMethod, exception, &unused, cause); 551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case kInitMsgThrow: 553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGVV("+++ exc msg+throw"); 554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(!needInitCause); 555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmCallMethod(self, initMethod, exception, &unused, msgStr, cause); 556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project default: 558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(false); 559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * It's possible the constructor has thrown an exception. If so, we 564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * return an error and let our caller deal with it. 565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (self->exception != NULL) { 567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGW("Exception thrown (%s) while throwing internal exception (%s)\n", 568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->exception->clazz->descriptor, exception->clazz->descriptor); 569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If this exception was caused by another exception, and we weren't 574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * able to find a cause-setting constructor, set the "cause" field 575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * with an explicit call. 576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (needInitCause) { 578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Method* initCause; 579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project initCause = dvmFindVirtualMethodHierByDescriptor(excepClass, "initCause", 580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "(Ljava/lang/Throwable;)Ljava/lang/Throwable;"); 581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (initCause != NULL) { 582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmCallMethod(self, initCause, exception, &unused, cause); 583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (self->exception != NULL) { 584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* initCause() threw an exception; return an error and 585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * let the caller deal with it. 586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGW("Exception thrown (%s) during initCause() " 588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "of internal exception (%s)\n", 589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->exception->clazz->descriptor, 590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project exception->clazz->descriptor); 591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGW("WARNING: couldn't find initCause in '%s'\n", 595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project excepClass->descriptor); 596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project result = true; 601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail: 603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmReleaseTrackedAlloc((Object*) msgStr, self); // NULL is ok 604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return result; 605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Clear the pending exception and the "initExceptionCount" counter. This 610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * is used by the optimization and verification code, which has to run with 611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "initializing" set to avoid going into a death-spin if the "class not 612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * found" exception can't be found. 613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This can also be called when the VM is in a "normal" state, e.g. when 615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * verifying classes that couldn't be verified at optimization time. The 616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * reset of initExceptionCount should be harmless in that case. 617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmClearOptException(Thread* self) 619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->exception = NULL; 621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gDvm.initExceptionCount = 0; 622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns "true" if this is a "checked" exception, i.e. it's a subclass 626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * of Throwable (assumed) but not a subclass of RuntimeException or Error. 627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbool dvmIsCheckedException(const Object* exception) 629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmInstanceof(exception->clazz, gDvm.classJavaLangError) || 631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmInstanceof(exception->clazz, gDvm.classJavaLangRuntimeException)) 632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Wrap the now-pending exception in a different exception. This is useful 641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * for reflection stuff that wants to hand a checked exception back from a 642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * method that doesn't declare it. 643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If something fails, an (unchecked) exception related to that failure 645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * will be pending instead. 646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmWrapException(const char* newExcepStr) 648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Thread* self = dvmThreadSelf(); 650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Object* origExcep; 651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ClassObject* iteClass; 652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project origExcep = dvmGetException(self); 654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmAddTrackedAlloc(origExcep, self); // don't let the GC free it 655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmClearException(self); // clear before class lookup 657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project iteClass = dvmFindSystemClass(newExcepStr); 658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (iteClass != NULL) { 659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Object* iteExcep; 660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Method* initMethod; 661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project iteExcep = dvmAllocObject(iteClass, ALLOC_DEFAULT); 663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (iteExcep != NULL) { 664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project initMethod = dvmFindDirectMethodByDescriptor(iteClass, "<init>", 665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "(Ljava/lang/Throwable;)V"); 666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (initMethod != NULL) { 667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project JValue unused; 668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmCallMethod(self, initMethod, iteExcep, &unused, 669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project origExcep); 670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* if <init> succeeded, replace the old exception */ 672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!dvmCheckException(self)) 673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmSetException(self, iteExcep); 674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 675f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmReleaseTrackedAlloc(iteExcep, NULL); 676f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* if initMethod doesn't exist, or failed... */ 678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!dvmCheckException(self)) 679f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmSetException(self, origExcep); 680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 681f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* leave OutOfMemoryError pending */ 682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 683f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* leave ClassNotFoundException pending */ 685f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(dvmCheckException(self)); 688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmReleaseTrackedAlloc(origExcep, self); 689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 692686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden * Get the "cause" field from an exception. 693686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden * 694686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden * The Throwable class initializes the "cause" field to "this" to 695686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden * differentiate between being initialized to null and never being 696686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden * initialized. We check for that here and convert it to NULL. 697686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden */ 698686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFaddenObject* dvmGetExceptionCause(const Object* exception) 699686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden{ 700686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden if (!dvmInstanceof(exception->clazz, gDvm.classJavaLangThrowable)) { 701686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden LOGE("Tried to get cause from object of type '%s'\n", 702686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden exception->clazz->descriptor); 703686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden dvmAbort(); 704686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden } 705686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden Object* cause = 706686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden dvmGetFieldObject(exception, gDvm.offJavaLangThrowable_cause); 707686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden if (cause == exception) 708686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden return NULL; 709686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden else 710686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden return cause; 711686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden} 712686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden 713686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden/* 714f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Print the stack trace of the current exception on stderr. This is called 715f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * from the JNI ExceptionDescribe call. 716f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * For consistency we just invoke the Throwable printStackTrace method, 718f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * which might be overridden in the exception object. 719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 720f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Exceptions thrown during the course of printing the stack trace are 721f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ignored. 722f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 723f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmPrintExceptionStackTrace(void) 724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 725f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Thread* self = dvmThreadSelf(); 726f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Object* exception; 727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Method* printMethod; 728f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project exception = self->exception; 730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (exception == NULL) 731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 733f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->exception = NULL; 734f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project printMethod = dvmFindVirtualMethodHierByDescriptor(exception->clazz, 735f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "printStackTrace", "()V"); 736f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (printMethod != NULL) { 737f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project JValue unused; 738f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmCallMethod(self, printMethod, exception, &unused); 739f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 740f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGW("WARNING: could not find printStackTrace in %s\n", 741f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project exception->clazz->descriptor); 742f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 744f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (self->exception != NULL) { 745f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGI("NOTE: exception thrown while printing stack trace: %s\n", 746f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->exception->clazz->descriptor); 747f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 748f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 749f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->exception = exception; 750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 751f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 752f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 753f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Search the method's list of exceptions for a match. 754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns the offset of the catch block on success, or -1 on failure. 756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int findCatchInMethod(Thread* self, const Method* method, int relPc, 758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ClassObject* excepClass) 759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Need to clear the exception before entry. Otherwise, dvmResolveClass 762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * might think somebody threw an exception while it was loading a class. 763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(!dvmCheckException(self)); 765f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(!dvmIsNativeMethod(method)); 766f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 767f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGVV("findCatchInMethod %s.%s excep=%s depth=%d\n", 768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project method->clazz->descriptor, method->name, excepClass->descriptor, 769f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmComputeExactFrameDepth(self->curFrame)); 770f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 771f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project DvmDex* pDvmDex = method->clazz->pDvmDex; 772f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const DexCode* pCode = dvmGetMethodCode(method); 773f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project DexCatchIterator iterator; 774f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 775f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dexFindCatchHandler(&iterator, pCode, relPc)) { 776f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (;;) { 777f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project DexCatchHandler* handler = dexCatchIteratorNext(&iterator); 778f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 779f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (handler == NULL) { 780f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 781f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 782f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 783f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (handler->typeIdx == kDexNoIndex) { 784f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* catch-all */ 785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGV("Match on catch-all block at 0x%02x in %s.%s for %s\n", 786f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project relPc, method->clazz->descriptor, 787f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project method->name, excepClass->descriptor); 788f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return handler->address; 789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ClassObject* throwable = 792f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmDexGetResolvedClass(pDvmDex, handler->typeIdx); 793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (throwable == NULL) { 794f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * TODO: this behaves badly if we run off the stack 796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * while trying to throw an exception. The problem is 797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * that, if we're in a class loaded by a class loader, 798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the call to dvmResolveClass has to ask the class 799f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * loader for help resolving any previously-unresolved 800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * classes. If this particular class loader hasn't 801f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * resolved StackOverflowError, it will call into 802f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * interpreted code, and blow up. 803f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 804f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We currently replace the previous exception with 805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the StackOverflowError, which means they won't be 806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * catching it *unless* they explicitly catch 807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * StackOverflowError, in which case we'll be unable 808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to resolve the class referred to by the "catch" 809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * block. 810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We end up getting a huge pile of warnings if we do 812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * a simple synthetic test, because this method gets 813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * called on every stack frame up the tree, and it 814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * fails every time. 815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This eventually bails out, effectively becoming an 817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * uncatchable exception, so other than the flurry of 818f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * warnings it's not really a problem. Still, we could 819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * probably handle this better. 820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 821f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throwable = dvmResolveClass(method->clazz, handler->typeIdx, 822f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project true); 823f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (throwable == NULL) { 824f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 825f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We couldn't find the exception they wanted in 826f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * our class files (or, perhaps, the stack blew up 827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * while we were querying a class loader). Cough 828f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * up a warning, then move on to the next entry. 829f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Keep the exception status clear. 830f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 831f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGW("Could not resolve class ref'ed in exception " 832f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project "catch list (class index %d, exception %s)\n", 833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project handler->typeIdx, 834f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (self->exception != NULL) ? 835f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->exception->clazz->descriptor : "(none)"); 836f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmClearException(self); 837f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project continue; 838f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 839f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 840f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 841f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //LOGD("ADDR MATCH, check %s instanceof %s\n", 842f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // excepClass->descriptor, pEntry->excepClass->descriptor); 843f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 844f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmInstanceof(excepClass, throwable)) { 845f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGV("Match on catch block at 0x%02x in %s.%s for %s\n", 846f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project relPc, method->clazz->descriptor, 847f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project method->name, excepClass->descriptor); 848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return handler->address; 849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 850f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 851f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 852f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 853f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGV("No matching catch block at 0x%02x in %s for %s\n", 854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project relPc, method->name, excepClass->descriptor); 855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return -1; 856f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 859f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Find a matching "catch" block. "pc" is the relative PC within the 860f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * current method, indicating the offset from the start in 16-bit units. 861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 862f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns the offset to the catch block, or -1 if we run up against a 863f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * break frame without finding anything. 864f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 865f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The class resolution stuff we have to do while evaluating the "catch" 866f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * blocks could cause an exception. The caller should clear the exception 867f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * before calling here and restore it after. 868f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 869f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Sets *newFrame to the frame pointer of the frame with the catch block. 870f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If "scanOnly" is false, self->curFrame is also set to this value. 871f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 872f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint dvmFindCatchBlock(Thread* self, int relPc, Object* exception, 873f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project bool scanOnly, void** newFrame) 874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project void* fp = self->curFrame; 876f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int catchAddr = -1; 877f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 878f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(!dvmCheckException(self)); 879f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 880f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project while (true) { 881f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StackSaveArea* saveArea = SAVEAREA_FROM_FP(fp); 882f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project catchAddr = findCatchInMethod(self, saveArea->method, relPc, 883f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project exception->clazz); 884f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (catchAddr >= 0) 885f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 886f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 887f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 888f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Normally we'd check for ACC_SYNCHRONIZED methods and unlock 889f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * them as we unroll. Dalvik uses what amount to generated 890f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "finally" blocks to take care of this for us. 891f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 892f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 893f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* output method profiling info */ 894f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!scanOnly) { 895f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project TRACE_METHOD_UNROLL(self, saveArea->method); 896f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 897f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 899f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Move up one frame. If the next thing up is a break frame, 900f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * break out now so we're left unrolled to the last method frame. 901f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We need to point there so we can roll up the JNI local refs 902f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * if this was a native method. 903f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 904f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(saveArea->prevFrame != NULL); 905f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsBreakFrame(saveArea->prevFrame)) { 906f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!scanOnly) 907f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; // bail with catchAddr == -1 908f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 909f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 910f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We're scanning for the debugger. It needs to know if this 911f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * exception is going to be caught or not, and we need to figure 912f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * out if it will be caught *ever* not just between the current 913f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * position and the next break frame. We can't tell what native 914f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * code is going to do, so we assume it never catches exceptions. 915f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 916f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Start by finding an interpreted code frame. 917f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 918f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project fp = saveArea->prevFrame; // this is the break frame 919f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveArea = SAVEAREA_FROM_FP(fp); 920f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project fp = saveArea->prevFrame; // this may be a good one 921f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project while (fp != NULL) { 922f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!dvmIsBreakFrame(fp)) { 923f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveArea = SAVEAREA_FROM_FP(fp); 924f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!dvmIsNativeMethod(saveArea->method)) 925f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 926f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 927f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 928f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project fp = SAVEAREA_FROM_FP(fp)->prevFrame; 929f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 930f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (fp == NULL) 931f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; // bail with catchAddr == -1 932f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 933f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 934f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Now fp points to the "good" frame. When the interp code 935f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * invoked the native code, it saved a copy of its current PC 936f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * into xtra.currentPc. Pull it out of there. 937f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 938f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project relPc = 939f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveArea->xtra.currentPc - SAVEAREA_FROM_FP(fp)->method->insns; 940f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 941f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project fp = saveArea->prevFrame; 942f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 943f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* savedPc in was-current frame goes with method in now-current */ 944f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project relPc = saveArea->savedPc - SAVEAREA_FROM_FP(fp)->method->insns; 945f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 946f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 947f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 948f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!scanOnly) 949f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->curFrame = fp; 950f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 951f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 952f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The class resolution in findCatchInMethod() could cause an exception. 953f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Clear it to be safe. 954f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 955f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project self->exception = NULL; 956f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 957f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *newFrame = fp; 958f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return catchAddr; 959f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 960f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 961f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 962f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We have to carry the exception's stack trace around, but in many cases 963f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * it will never be examined. It makes sense to keep it in a compact, 964f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * VM-specific object, rather than an array of Objects with strings. 965f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 966f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Pass in the thread whose stack we're interested in. If "thread" is 967f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * not self, the thread must be suspended. This implies that the thread 968f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * list lock is held, which means we can't allocate objects or we risk 969f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * jamming the GC. So, we allow this function to return different formats. 970f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (This shouldn't be called directly -- see the inline functions in the 971f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * header file.) 972f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 973f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If "wantObject" is true, this returns a newly-allocated Object, which is 974f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * presently an array of integers, but could become something else in the 975f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * future. If "wantObject" is false, return plain malloc data. 976f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 977f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * NOTE: if we support class unloading, we will need to scan the class 978f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * object references out of these arrays. 979f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 980f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid* dvmFillInStackTraceInternal(Thread* thread, bool wantObject, int* pCount) 981f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 982f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ArrayObject* stackData = NULL; 983f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int* simpleData = NULL; 984f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project void* fp; 985f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project void* startFp; 986f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int stackDepth; 987f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int* intPtr; 988f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 989f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (pCount != NULL) 990f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *pCount = 0; 991f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project fp = thread->curFrame; 992f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 993f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(thread == dvmThreadSelf() || dvmIsSuspended(thread)); 994f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 995f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 996f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We're looking at a stack frame for code running below a Throwable 997f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * constructor. We want to remove the Throwable methods and the 998f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * superclass initializations so the user doesn't see them when they 999f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * read the stack dump. 1000f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1001f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * TODO: this just scrapes off the top layers of Throwable. Might not do 1002f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the right thing if we create an exception object or cause a VM 1003f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * exception while in a Throwable method. 1004f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1005f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project while (fp != NULL) { 1006f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const StackSaveArea* saveArea = SAVEAREA_FROM_FP(fp); 1007f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const Method* method = saveArea->method; 1008f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1009f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsBreakFrame(fp)) 1010f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 1011f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!dvmInstanceof(method->clazz, gDvm.classJavaLangThrowable)) 1012f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 1013f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //LOGD("EXCEP: ignoring %s.%s\n", 1014f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // method->clazz->descriptor, method->name); 1015f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project fp = saveArea->prevFrame; 1016f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1017f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project startFp = fp; 1018f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1019f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 1020f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Compute the stack depth. 1021f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1022f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackDepth = 0; 1023f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project while (fp != NULL) { 1024f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const StackSaveArea* saveArea = SAVEAREA_FROM_FP(fp); 1025f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1026f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!dvmIsBreakFrame(fp)) 1027f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackDepth++; 1028f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1029f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(fp != saveArea->prevFrame); 1030f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project fp = saveArea->prevFrame; 1031f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1032f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //LOGD("EXCEP: stack depth is %d\n", stackDepth); 1033f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1034f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!stackDepth) 1035f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 1036f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1037f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 1038f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We need to store a pointer to the Method and the program counter. 1039f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We have 4-byte pointers, so we use '[I'. 1040f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1041f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (wantObject) { 1042f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(sizeof(Method*) == 4); 1043f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackData = dvmAllocPrimitiveArray('I', stackDepth*2, ALLOC_DEFAULT); 1044f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (stackData == NULL) { 1045f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(dvmCheckException(dvmThreadSelf())); 1046f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 1047f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1048f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project intPtr = (int*) stackData->contents; 1049f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 1050f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* array of ints; first entry is stack depth */ 1051f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(sizeof(Method*) == sizeof(int)); 1052f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project simpleData = (int*) malloc(sizeof(int) * stackDepth*2); 1053f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (simpleData == NULL) 1054f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 1055f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1056f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(pCount != NULL); 1057f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project intPtr = simpleData; 1058f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1059f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (pCount != NULL) 1060f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *pCount = stackDepth; 1061f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1062f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project fp = startFp; 1063f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project while (fp != NULL) { 1064f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const StackSaveArea* saveArea = SAVEAREA_FROM_FP(fp); 1065f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const Method* method = saveArea->method; 1066f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1067f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!dvmIsBreakFrame(fp)) { 1068f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //LOGD("EXCEP keeping %s.%s\n", method->clazz->descriptor, 1069f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // method->name); 1070f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1071f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *intPtr++ = (int) method; 1072f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsNativeMethod(method)) { 1073f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *intPtr++ = 0; /* no saved PC for native methods */ 1074f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 1075f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(saveArea->xtra.currentPc >= method->insns && 1076f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project saveArea->xtra.currentPc < 1077f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project method->insns + dvmGetMethodInsnsSize(method)); 1078f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *intPtr++ = (int) (saveArea->xtra.currentPc - method->insns); 1079f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1080f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1081f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackDepth--; // for verification 1082f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1083f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1084f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(fp != saveArea->prevFrame); 1085f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project fp = saveArea->prevFrame; 1086f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1087f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(stackDepth == 0); 1088f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1089f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail: 1090f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (wantObject) { 1091f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmReleaseTrackedAlloc((Object*) stackData, dvmThreadSelf()); 1092f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return stackData; 1093f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 1094f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return simpleData; 1095f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1096f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1097f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1098f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1099f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Given an Object previously created by dvmFillInStackTrace(), use the 1101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * contents of the saved stack trace to generate an array of 1102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * java/lang/StackTraceElement objects. 1103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The returned array is not added to the "local refs" list. 1105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectArrayObject* dvmGetStackTrace(const Object* ostackData) 1107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const ArrayObject* stackData = (const ArrayObject*) ostackData; 1109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const int* intVals; 1110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int i, stackSize; 1111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackSize = stackData->length / 2; 1113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project intVals = (const int*) stackData->contents; 1114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return dvmGetStackTraceRaw(intVals, stackSize); 1115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Generate an array of StackTraceElement objects from the raw integer 1119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * data encoded by dvmFillInStackTrace(). 1120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "intVals" points to the first {method,pc} pair. 1122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The returned array is not added to the "local refs" list. 1124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source ProjectArrayObject* dvmGetStackTraceRaw(const int* intVals, int stackDepth) 1126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ArrayObject* steArray = NULL; 1128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Object** stePtr; 1129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int i; 1130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* init this if we haven't yet */ 1132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!dvmIsClassInitialized(gDvm.classJavaLangStackTraceElement)) 1133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmInitClass(gDvm.classJavaLangStackTraceElement); 1134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* allocate a StackTraceElement array */ 1136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project steArray = dvmAllocArray(gDvm.classJavaLangStackTraceElementArray, 1137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackDepth, kObjectArrayRefWidth, ALLOC_DEFAULT); 1138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (steArray == NULL) 1139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 1140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stePtr = (Object**) steArray->contents; 1141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 1143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Allocate and initialize a StackTraceElement for each stack frame. 1144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We use the standard constructor to configure the object. 1145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (i = 0; i < stackDepth; i++) { 1147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Object* ste; 1148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Method* meth; 1149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StringObject* className; 1150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StringObject* methodName; 1151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StringObject* fileName; 1152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int lineNumber, pc; 1153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const char* sourceFile; 1154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project char* dotName; 1155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ste = dvmAllocObject(gDvm.classJavaLangStackTraceElement,ALLOC_DEFAULT); 1157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (ste == NULL) 1158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 1159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project meth = (Method*) *intVals++; 1161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pc = *intVals++; 1162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (pc == -1) // broken top frame? 1164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project lineNumber = 0; 1165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else 1166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project lineNumber = dvmLineNumFromPC(meth, pc); 1167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dotName = dvmDescriptorToDot(meth->clazz->descriptor); 1169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project className = dvmCreateStringFromCstr(dotName, ALLOC_DEFAULT); 1170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(dotName); 1171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project methodName = dvmCreateStringFromCstr(meth->name, ALLOC_DEFAULT); 1173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sourceFile = dvmGetMethodSourceFile(meth); 1174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (sourceFile != NULL) 1175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project fileName = dvmCreateStringFromCstr(sourceFile, ALLOC_DEFAULT); 1176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else 1177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project fileName = NULL; 1178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 1180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Invoke: 1181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * public StackTraceElement(String declaringClass, String methodName, 1182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * String fileName, int lineNumber) 1183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (where lineNumber==-2 means "native") 1184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project JValue unused; 1186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmCallMethod(dvmThreadSelf(), gDvm.methJavaLangStackTraceElement_init, 1187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ste, &unused, className, methodName, fileName, lineNumber); 1188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmReleaseTrackedAlloc(ste, NULL); 1190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmReleaseTrackedAlloc((Object*) className, NULL); 1191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmReleaseTrackedAlloc((Object*) methodName, NULL); 1192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmReleaseTrackedAlloc((Object*) fileName, NULL); 1193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmCheckException(dvmThreadSelf())) 1195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 1196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *stePtr++ = ste; 1198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail: 1201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmReleaseTrackedAlloc((Object*) steArray, NULL); 1202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return steArray; 1203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dump the contents of a raw stack trace to the log. 1207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmLogRawStackTrace(const int* intVals, int stackDepth) 1209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int i; 1211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 1213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Run through the array of stack frame data. 1214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (i = 0; i < stackDepth; i++) { 1216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Method* meth; 1217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int lineNumber, pc; 1218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const char* sourceFile; 1219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project char* dotName; 1220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project meth = (Method*) *intVals++; 1222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pc = *intVals++; 1223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (pc == -1) // broken top frame? 1225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project lineNumber = 0; 1226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else 1227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project lineNumber = dvmLineNumFromPC(meth, pc); 1228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // probably don't need to do this, but it looks nicer 1230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dotName = dvmDescriptorToDot(meth->clazz->descriptor); 1231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmIsNativeMethod(meth)) { 1233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGI("\tat %s.%s(Native Method)\n", dotName, meth->name); 1234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 1235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGI("\tat %s.%s(%s:%d)\n", 1236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dotName, meth->name, dvmGetMethodSourceFile(meth), 1237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmLineNumFromPC(meth, pc)); 1238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(dotName); 1241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sourceFile = dvmGetMethodSourceFile(meth); 1243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Print the direct stack trace of the given exception to the log. 1248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void logStackTraceOf(Object* exception) 1250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const ArrayObject* stackData; 1252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StringObject* messageStr; 1253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int stackSize; 1254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const int* intVals; 1255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project messageStr = (StringObject*) dvmGetFieldObject(exception, 1257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gDvm.offJavaLangThrowable_message); 1258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (messageStr != NULL) { 1259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project char* cp = dvmCreateCstrFromString(messageStr); 1260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGI("%s: %s\n", exception->clazz->descriptor, cp); 1261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(cp); 1262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 1263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGI("%s:\n", exception->clazz->descriptor); 1264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackData = (const ArrayObject*) dvmGetFieldObject(exception, 1267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gDvm.offJavaLangThrowable_stackState); 1268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (stackData == NULL) { 1269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGI(" (no stack trace data found)\n"); 1270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 1271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stackSize = stackData->length / 2; 1274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project intVals = (const int*) stackData->contents; 1275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmLogRawStackTrace(intVals, stackSize); 1277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 1280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Print the stack trace of the current thread's exception, as well as 1281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the stack traces of any chained exceptions, to the log. We extract 1282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the stored stack trace and process it internally instead of calling 1283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * interpreted code. 1284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmLogExceptionStackTrace(void) 1286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Object* exception = dvmThreadSelf()->exception; 1288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Object* cause; 1289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (exception == NULL) { 1291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGW("tried to log a null exception?\n"); 1292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 1293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (;;) { 1296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project logStackTraceOf(exception); 1297686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden cause = dvmGetExceptionCause(exception); 1298686e1e23324f1c1f358f29f13f23e57b41c00eaaAndy McFadden if (cause == NULL) { 1299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 1300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGI("Caused by:\n"); 1302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project exception = cause; 1303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 1304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 1305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 1306