1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 /* 18 * Exception handling. 19 */ 20 #ifndef _DALVIK_EXCEPTION 21 #define _DALVIK_EXCEPTION 22 23 /* initialization */ 24 bool dvmExceptionStartup(void); 25 void dvmExceptionShutdown(void); 26 27 /* 28 * Throw an exception in the current thread, by class descriptor. 29 */ 30 void dvmThrowChainedException(const char* exceptionDescriptor, const char* msg, 31 Object* cause); 32 INLINE void dvmThrowException(const char* exceptionDescriptor, 33 const char* msg) 34 { 35 dvmThrowChainedException(exceptionDescriptor, msg, NULL); 36 } 37 38 /* 39 * Like dvmThrowChainedException, but takes printf-style args for the message. 40 */ 41 void dvmThrowExceptionFmtV(const char* exceptionDescriptor, const char* fmt, 42 va_list args); 43 void dvmThrowExceptionFmt(const char* exceptionDescriptor, const char* fmt, ...) 44 #if defined(__GNUC__) 45 __attribute__ ((format(printf, 2, 3))) 46 #endif 47 ; 48 INLINE void dvmThrowExceptionFmt(const char* exceptionDescriptor, 49 const char* fmt, ...) 50 { 51 va_list args; 52 va_start(args, fmt); 53 dvmThrowExceptionFmtV(exceptionDescriptor, fmt, args); 54 va_end(args); 55 } 56 57 /* 58 * Throw an exception in the current thread, by class object. 59 */ 60 void dvmThrowChainedExceptionByClass(ClassObject* exceptionClass, 61 const char* msg, Object* cause); 62 INLINE void dvmThrowExceptionByClass(ClassObject* exceptionClass, 63 const char* msg) 64 { 65 dvmThrowChainedExceptionByClass(exceptionClass, msg, NULL); 66 } 67 68 /* 69 * Throw the named exception using the name of a class as the exception 70 * message. 71 */ 72 void dvmThrowChainedExceptionWithClassMessage(const char* exceptionDescriptor, 73 const char* messageDescriptor, Object* cause); 74 INLINE void dvmThrowExceptionWithClassMessage(const char* exceptionDescriptor, 75 const char* messageDescriptor) 76 { 77 dvmThrowChainedExceptionWithClassMessage(exceptionDescriptor, 78 messageDescriptor, NULL); 79 } 80 81 /* 82 * Like dvmThrowExceptionWithMessageFromDescriptor, but take a 83 * class object instead of a name. 84 */ 85 void dvmThrowExceptionByClassWithClassMessage(ClassObject* exceptionClass, 86 const char* messageDescriptor); 87 88 /* 89 * Return the exception being thrown in the current thread, or NULL if 90 * no exception is pending. 91 */ 92 INLINE Object* dvmGetException(Thread* self) { 93 return self->exception; 94 } 95 96 /* 97 * Set the exception being thrown in the current thread. 98 */ 99 INLINE void dvmSetException(Thread* self, Object* exception) 100 { 101 assert(exception != NULL); 102 self->exception = exception; 103 } 104 105 /* 106 * Clear the pending exception. 107 * 108 * (We use this rather than "set(null)" because we may need to have special 109 * fixups here for StackOverflowError stuff. Calling "clear" in the code 110 * makes it obvious.) 111 */ 112 INLINE void dvmClearException(Thread* self) { 113 self->exception = NULL; 114 } 115 116 /* 117 * Clear the pending exception. Used by the optimization and verification 118 * code, which has to run with "initializing" set to avoid going into a 119 * death-spin if the "class not found" exception can't be found. 120 */ 121 void dvmClearOptException(Thread* self); 122 123 /* 124 * Returns "true" if an exception is pending. Use this if you have a 125 * "self" pointer. 126 */ 127 INLINE bool dvmCheckException(Thread* self) { 128 return (self->exception != NULL); 129 } 130 131 /* 132 * Returns "true" if this is a "checked" exception, i.e. it's a subclass 133 * of Throwable (assumed) but not a subclass of RuntimeException or Error. 134 */ 135 bool dvmIsCheckedException(const Object* exception); 136 137 /* 138 * Wrap the now-pending exception in a different exception. 139 * 140 * If something fails, an (unchecked) exception related to that failure 141 * will be pending instead. 142 */ 143 void dvmWrapException(const char* newExcepStr); 144 145 /* 146 * Get the "cause" field from an exception. 147 * 148 * Returns NULL if the field is null or uninitialized. 149 */ 150 Object* dvmGetExceptionCause(const Object* exception); 151 152 /* 153 * Print the exception stack trace on stderr. Calls the exception's 154 * print function. 155 */ 156 void dvmPrintExceptionStackTrace(void); 157 158 /* 159 * Print the exception stack trace to the log file. The exception stack 160 * trace is computed within the VM. 161 */ 162 void dvmLogExceptionStackTrace(void); 163 164 /* 165 * Search for a catch block that matches "exception". 166 * 167 * "*newFrame" gets a copy of the new frame pointer. 168 * 169 * If "doUnroll" is set, we unroll "thread"s stack as we go (and update 170 * self->curFrame with the same value as in *newFrame). 171 * 172 * Returns the offset to the catch code on success, or -1 if we couldn't 173 * find a catcher. 174 */ 175 int dvmFindCatchBlock(Thread* self, int relPc, Object* exception, 176 bool doUnroll, void** newFrame); 177 178 /* 179 * Support for saving exception stack traces and converting them to 180 * usable form. Use the "FillIn" function to generate a compact array 181 * that represents the stack frames, then "GetStackTrace" to convert it 182 * to an array of StackTraceElement objects. 183 * 184 * Don't call the "Internal" form of the function directly. 185 */ 186 void* dvmFillInStackTraceInternal(Thread* thread, bool wantObject, int* pCount); 187 /* return an [I for use by interpreted code */ 188 INLINE Object* dvmFillInStackTrace(Thread* thread) { 189 return (Object*) dvmFillInStackTraceInternal(thread, true, NULL); 190 } 191 ArrayObject* dvmGetStackTrace(const Object* stackState); 192 /* return an int* and array count; caller must free() the return value */ 193 INLINE int* dvmFillInStackTraceRaw(Thread* thread, int* pCount) { 194 return (int*) dvmFillInStackTraceInternal(thread, false, pCount); 195 } 196 ArrayObject* dvmGetStackTraceRaw(const int* intVals, int stackDepth); 197 198 /* 199 * Print a formatted version of a raw stack trace to the log file. 200 */ 201 void dvmLogRawStackTrace(const int* intVals, int stackDepth); 202 203 #endif /*_DALVIK_EXCEPTION*/ 204