1 /* 2 * Copyright (C) 2012 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 #include "common_throws.h" 18 19 #include "base/logging.h" 20 #include "class_linker-inl.h" 21 #include "dex_file-inl.h" 22 #include "dex_instruction-inl.h" 23 #include "invoke_type.h" 24 #include "mirror/art_method-inl.h" 25 #include "mirror/class-inl.h" 26 #include "mirror/object-inl.h" 27 #include "mirror/object_array-inl.h" 28 #include "object_utils.h" 29 #include "thread.h" 30 #include "verifier/method_verifier.h" 31 32 #include <sstream> 33 34 namespace art { 35 36 static void AddReferrerLocation(std::ostream& os, const mirror::Class* referrer) 37 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 38 if (referrer != NULL) { 39 ClassHelper kh(referrer); 40 std::string location(kh.GetLocation()); 41 if (!location.empty()) { 42 os << " (declaration of '" << PrettyDescriptor(referrer) 43 << "' appears in " << location << ")"; 44 } 45 } 46 } 47 48 static void ThrowException(const ThrowLocation* throw_location, const char* exception_descriptor, 49 const mirror::Class* referrer, const char* fmt, va_list* args = NULL) 50 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 51 std::ostringstream msg; 52 if (args != NULL) { 53 std::string vmsg; 54 StringAppendV(&vmsg, fmt, *args); 55 msg << vmsg; 56 } else { 57 msg << fmt; 58 } 59 AddReferrerLocation(msg, referrer); 60 Thread* self = Thread::Current(); 61 if (throw_location == NULL) { 62 ThrowLocation computed_throw_location = self->GetCurrentLocationForThrow(); 63 self->ThrowNewException(computed_throw_location, exception_descriptor, msg.str().c_str()); 64 } else { 65 self->ThrowNewException(*throw_location, exception_descriptor, msg.str().c_str()); 66 } 67 } 68 69 // AbstractMethodError 70 71 void ThrowAbstractMethodError(const mirror::ArtMethod* method) { 72 ThrowException(NULL, "Ljava/lang/AbstractMethodError;", NULL, 73 StringPrintf("abstract method \"%s\"", 74 PrettyMethod(method).c_str()).c_str()); 75 } 76 77 // ArithmeticException 78 79 void ThrowArithmeticExceptionDivideByZero() { 80 ThrowException(NULL, "Ljava/lang/ArithmeticException;", NULL, "divide by zero"); 81 } 82 83 // ArrayIndexOutOfBoundsException 84 85 void ThrowArrayIndexOutOfBoundsException(int index, int length) { 86 ThrowException(NULL, "Ljava/lang/ArrayIndexOutOfBoundsException;", NULL, 87 StringPrintf("length=%d; index=%d", length, index).c_str()); 88 } 89 90 // ArrayStoreException 91 92 void ThrowArrayStoreException(const mirror::Class* element_class, 93 const mirror::Class* array_class) { 94 ThrowException(NULL, "Ljava/lang/ArrayStoreException;", NULL, 95 StringPrintf("%s cannot be stored in an array of type %s", 96 PrettyDescriptor(element_class).c_str(), 97 PrettyDescriptor(array_class).c_str()).c_str()); 98 } 99 100 // ClassCastException 101 102 void ThrowClassCastException(const mirror::Class* dest_type, const mirror::Class* src_type) { 103 ThrowException(NULL, "Ljava/lang/ClassCastException;", NULL, 104 StringPrintf("%s cannot be cast to %s", 105 PrettyDescriptor(src_type).c_str(), 106 PrettyDescriptor(dest_type).c_str()).c_str()); 107 } 108 109 void ThrowClassCastException(const ThrowLocation* throw_location, const char* msg) { 110 ThrowException(throw_location, "Ljava/lang/ClassCastException;", NULL, msg); 111 } 112 113 // ClassCircularityError 114 115 void ThrowClassCircularityError(mirror::Class* c) { 116 std::ostringstream msg; 117 msg << PrettyDescriptor(c); 118 ThrowException(NULL, "Ljava/lang/ClassCircularityError;", c, msg.str().c_str()); 119 } 120 121 // ClassFormatError 122 123 void ThrowClassFormatError(const mirror::Class* referrer, const char* fmt, ...) { 124 va_list args; 125 va_start(args, fmt); 126 ThrowException(NULL, "Ljava/lang/ClassFormatError;", referrer, fmt, &args); 127 va_end(args);} 128 129 // IllegalAccessError 130 131 void ThrowIllegalAccessErrorClass(mirror::Class* referrer, mirror::Class* accessed) { 132 std::ostringstream msg; 133 msg << "Illegal class access: '" << PrettyDescriptor(referrer) << "' attempting to access '" 134 << PrettyDescriptor(accessed) << "'"; 135 ThrowException(NULL, "Ljava/lang/IllegalAccessError;", referrer, msg.str().c_str()); 136 } 137 138 void ThrowIllegalAccessErrorClassForMethodDispatch(mirror::Class* referrer, mirror::Class* accessed, 139 const mirror::ArtMethod* caller, 140 const mirror::ArtMethod* called, 141 InvokeType type) { 142 std::ostringstream msg; 143 msg << "Illegal class access ('" << PrettyDescriptor(referrer) << "' attempting to access '" 144 << PrettyDescriptor(accessed) << "') in attempt to invoke " << type 145 << " method " << PrettyMethod(called).c_str(); 146 ThrowException(NULL, "Ljava/lang/IllegalAccessError;", referrer, msg.str().c_str()); 147 } 148 149 void ThrowIllegalAccessErrorMethod(mirror::Class* referrer, mirror::ArtMethod* accessed) { 150 std::ostringstream msg; 151 msg << "Method '" << PrettyMethod(accessed) << "' is inaccessible to class '" 152 << PrettyDescriptor(referrer) << "'"; 153 ThrowException(NULL, "Ljava/lang/IllegalAccessError;", referrer, msg.str().c_str()); 154 } 155 156 void ThrowIllegalAccessErrorField(mirror::Class* referrer, mirror::ArtField* accessed) { 157 std::ostringstream msg; 158 msg << "Field '" << PrettyField(accessed, false) << "' is inaccessible to class '" 159 << PrettyDescriptor(referrer) << "'"; 160 ThrowException(NULL, "Ljava/lang/IllegalAccessError;", referrer, msg.str().c_str()); 161 } 162 163 void ThrowIllegalAccessErrorFinalField(const mirror::ArtMethod* referrer, 164 mirror::ArtField* accessed) { 165 std::ostringstream msg; 166 msg << "Final field '" << PrettyField(accessed, false) << "' cannot be written to by method '" 167 << PrettyMethod(referrer) << "'"; 168 ThrowException(NULL, "Ljava/lang/IllegalAccessError;", 169 referrer != NULL ? referrer->GetClass() : NULL, 170 msg.str().c_str()); 171 } 172 173 void ThrowIllegalAccessError(mirror::Class* referrer, const char* fmt, ...) { 174 va_list args; 175 va_start(args, fmt); 176 ThrowException(NULL, "Ljava/lang/IllegalAccessError;", referrer, fmt, &args); 177 va_end(args); 178 } 179 180 // IllegalArgumentException 181 182 void ThrowIllegalArgumentException(const ThrowLocation* throw_location, const char* msg) { 183 ThrowException(throw_location, "Ljava/lang/IllegalArgumentException;", NULL, msg); 184 } 185 186 187 // IncompatibleClassChangeError 188 189 void ThrowIncompatibleClassChangeError(InvokeType expected_type, InvokeType found_type, 190 mirror::ArtMethod* method, 191 const mirror::ArtMethod* referrer) { 192 std::ostringstream msg; 193 msg << "The method '" << PrettyMethod(method) << "' was expected to be of type " 194 << expected_type << " but instead was found to be of type " << found_type; 195 ThrowException(NULL, "Ljava/lang/IncompatibleClassChangeError;", 196 referrer != NULL ? referrer->GetClass() : NULL, 197 msg.str().c_str()); 198 } 199 200 void ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(const mirror::ArtMethod* interface_method, 201 mirror::Object* this_object, 202 const mirror::ArtMethod* referrer) { 203 // Referrer is calling interface_method on this_object, however, the interface_method isn't 204 // implemented by this_object. 205 CHECK(this_object != NULL); 206 std::ostringstream msg; 207 msg << "Class '" << PrettyDescriptor(this_object->GetClass()) 208 << "' does not implement interface '" 209 << PrettyDescriptor(interface_method->GetDeclaringClass()) 210 << "' in call to '" << PrettyMethod(interface_method) << "'"; 211 ThrowException(NULL, "Ljava/lang/IncompatibleClassChangeError;", 212 referrer != NULL ? referrer->GetClass() : NULL, 213 msg.str().c_str()); 214 } 215 216 void ThrowIncompatibleClassChangeErrorField(const mirror::ArtField* resolved_field, bool is_static, 217 const mirror::ArtMethod* referrer) { 218 std::ostringstream msg; 219 msg << "Expected '" << PrettyField(resolved_field) << "' to be a " 220 << (is_static ? "static" : "instance") << " field" << " rather than a " 221 << (is_static ? "instance" : "static") << " field"; 222 ThrowException(NULL, "Ljava/lang/IncompatibleClassChangeError;", referrer->GetClass(), 223 msg.str().c_str()); 224 } 225 226 void ThrowIncompatibleClassChangeError(const mirror::Class* referrer, const char* fmt, ...) { 227 va_list args; 228 va_start(args, fmt); 229 ThrowException(NULL, "Ljava/lang/IncompatibleClassChangeError;", referrer, fmt, &args); 230 va_end(args); 231 } 232 233 // LinkageError 234 235 void ThrowLinkageError(const mirror::Class* referrer, const char* fmt, ...) { 236 va_list args; 237 va_start(args, fmt); 238 ThrowException(NULL, "Ljava/lang/LinkageError;", referrer, fmt, &args); 239 va_end(args); 240 } 241 242 // NegativeArraySizeException 243 244 void ThrowNegativeArraySizeException(int size) { 245 ThrowException(NULL, "Ljava/lang/NegativeArraySizeException;", NULL, 246 StringPrintf("%d", size).c_str()); 247 } 248 249 void ThrowNegativeArraySizeException(const char* msg) { 250 ThrowException(NULL, "Ljava/lang/NegativeArraySizeException;", NULL, msg); 251 } 252 253 // NoSuchFieldError 254 255 void ThrowNoSuchFieldError(const StringPiece& scope, mirror::Class* c, 256 const StringPiece& type, const StringPiece& name) 257 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 258 ClassHelper kh(c); 259 std::ostringstream msg; 260 msg << "No " << scope << "field " << name << " of type " << type 261 << " in class " << kh.GetDescriptor() << " or its superclasses"; 262 ThrowException(NULL, "Ljava/lang/NoSuchFieldError;", c, msg.str().c_str()); 263 } 264 265 // NoSuchMethodError 266 267 void ThrowNoSuchMethodError(InvokeType type, mirror::Class* c, const StringPiece& name, 268 const StringPiece& signature) { 269 std::ostringstream msg; 270 ClassHelper kh(c); 271 msg << "No " << type << " method " << name << signature 272 << " in class " << kh.GetDescriptor() << " or its super classes"; 273 ThrowException(NULL, "Ljava/lang/NoSuchMethodError;", c, msg.str().c_str()); 274 } 275 276 void ThrowNoSuchMethodError(uint32_t method_idx) { 277 Thread* self = Thread::Current(); 278 ThrowLocation throw_location = self->GetCurrentLocationForThrow(); 279 mirror::DexCache* dex_cache = throw_location.GetMethod()->GetDeclaringClass()->GetDexCache(); 280 const DexFile& dex_file = *dex_cache->GetDexFile(); 281 std::ostringstream msg; 282 msg << "No method '" << PrettyMethod(method_idx, dex_file, true) << "'"; 283 ThrowException(&throw_location, "Ljava/lang/NoSuchMethodError;", 284 throw_location.GetMethod()->GetDeclaringClass(), msg.str().c_str()); 285 } 286 287 // NullPointerException 288 289 void ThrowNullPointerExceptionForFieldAccess(const ThrowLocation& throw_location, 290 mirror::ArtField* field, bool is_read) { 291 std::ostringstream msg; 292 msg << "Attempt to " << (is_read ? "read from" : "write to") 293 << " field '" << PrettyField(field, true) << "' on a null object reference"; 294 ThrowException(&throw_location, "Ljava/lang/NullPointerException;", NULL, msg.str().c_str()); 295 } 296 297 static void ThrowNullPointerExceptionForMethodAccessImpl(const ThrowLocation& throw_location, 298 uint32_t method_idx, 299 const DexFile& dex_file, 300 InvokeType type) 301 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 302 std::ostringstream msg; 303 msg << "Attempt to invoke " << type << " method '" 304 << PrettyMethod(method_idx, dex_file, true) << "' on a null object reference"; 305 ThrowException(&throw_location, "Ljava/lang/NullPointerException;", NULL, msg.str().c_str()); 306 } 307 308 void ThrowNullPointerExceptionForMethodAccess(const ThrowLocation& throw_location, 309 uint32_t method_idx, 310 InvokeType type) { 311 mirror::DexCache* dex_cache = throw_location.GetMethod()->GetDeclaringClass()->GetDexCache(); 312 const DexFile& dex_file = *dex_cache->GetDexFile(); 313 ThrowNullPointerExceptionForMethodAccessImpl(throw_location, method_idx, 314 dex_file, type); 315 } 316 317 void ThrowNullPointerExceptionForMethodAccess(const ThrowLocation& throw_location, 318 mirror::ArtMethod* method, 319 InvokeType type) { 320 mirror::DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache(); 321 const DexFile& dex_file = *dex_cache->GetDexFile(); 322 ThrowNullPointerExceptionForMethodAccessImpl(throw_location, method->GetDexMethodIndex(), 323 dex_file, type); 324 } 325 326 void ThrowNullPointerExceptionFromDexPC(const ThrowLocation& throw_location) { 327 const DexFile::CodeItem* code = MethodHelper(throw_location.GetMethod()).GetCodeItem(); 328 uint32_t throw_dex_pc = throw_location.GetDexPc(); 329 CHECK_LT(throw_dex_pc, code->insns_size_in_code_units_); 330 const Instruction* instr = Instruction::At(&code->insns_[throw_dex_pc]); 331 switch (instr->Opcode()) { 332 case Instruction::INVOKE_DIRECT: 333 ThrowNullPointerExceptionForMethodAccess(throw_location, instr->VRegB_35c(), kDirect); 334 break; 335 case Instruction::INVOKE_DIRECT_RANGE: 336 ThrowNullPointerExceptionForMethodAccess(throw_location, instr->VRegB_3rc(), kDirect); 337 break; 338 case Instruction::INVOKE_VIRTUAL: 339 ThrowNullPointerExceptionForMethodAccess(throw_location, instr->VRegB_35c(), kVirtual); 340 break; 341 case Instruction::INVOKE_VIRTUAL_RANGE: 342 ThrowNullPointerExceptionForMethodAccess(throw_location, instr->VRegB_3rc(), kVirtual); 343 break; 344 case Instruction::INVOKE_INTERFACE: 345 ThrowNullPointerExceptionForMethodAccess(throw_location, instr->VRegB_35c(), kInterface); 346 break; 347 case Instruction::INVOKE_INTERFACE_RANGE: 348 ThrowNullPointerExceptionForMethodAccess(throw_location, instr->VRegB_3rc(), kInterface); 349 break; 350 case Instruction::INVOKE_VIRTUAL_QUICK: 351 case Instruction::INVOKE_VIRTUAL_RANGE_QUICK: { 352 // Since we replaced the method index, we ask the verifier to tell us which 353 // method is invoked at this location. 354 mirror::ArtMethod* method = 355 verifier::MethodVerifier::FindInvokedMethodAtDexPc(throw_location.GetMethod(), 356 throw_location.GetDexPc()); 357 if (method != NULL) { 358 // NPE with precise message. 359 ThrowNullPointerExceptionForMethodAccess(throw_location, method, kVirtual); 360 } else { 361 // NPE with imprecise message. 362 ThrowNullPointerException(&throw_location, 363 "Attempt to invoke a virtual method on a null object reference"); 364 } 365 break; 366 } 367 case Instruction::IGET: 368 case Instruction::IGET_WIDE: 369 case Instruction::IGET_OBJECT: 370 case Instruction::IGET_BOOLEAN: 371 case Instruction::IGET_BYTE: 372 case Instruction::IGET_CHAR: 373 case Instruction::IGET_SHORT: { 374 mirror::ArtField* field = 375 Runtime::Current()->GetClassLinker()->ResolveField(instr->VRegC_22c(), 376 throw_location.GetMethod(), false); 377 ThrowNullPointerExceptionForFieldAccess(throw_location, field, true /* read */); 378 break; 379 } 380 case Instruction::IGET_QUICK: 381 case Instruction::IGET_WIDE_QUICK: 382 case Instruction::IGET_OBJECT_QUICK: { 383 // Since we replaced the field index, we ask the verifier to tell us which 384 // field is accessed at this location. 385 mirror::ArtField* field = 386 verifier::MethodVerifier::FindAccessedFieldAtDexPc(throw_location.GetMethod(), 387 throw_location.GetDexPc()); 388 if (field != NULL) { 389 // NPE with precise message. 390 ThrowNullPointerExceptionForFieldAccess(throw_location, field, true /* read */); 391 } else { 392 // NPE with imprecise message. 393 ThrowNullPointerException(&throw_location, 394 "Attempt to read from a field on a null object reference"); 395 } 396 break; 397 } 398 case Instruction::IPUT: 399 case Instruction::IPUT_WIDE: 400 case Instruction::IPUT_OBJECT: 401 case Instruction::IPUT_BOOLEAN: 402 case Instruction::IPUT_BYTE: 403 case Instruction::IPUT_CHAR: 404 case Instruction::IPUT_SHORT: { 405 mirror::ArtField* field = 406 Runtime::Current()->GetClassLinker()->ResolveField(instr->VRegC_22c(), 407 throw_location.GetMethod(), false); 408 ThrowNullPointerExceptionForFieldAccess(throw_location, field, false /* write */); 409 break; 410 } 411 case Instruction::IPUT_QUICK: 412 case Instruction::IPUT_WIDE_QUICK: 413 case Instruction::IPUT_OBJECT_QUICK: { 414 // Since we replaced the field index, we ask the verifier to tell us which 415 // field is accessed at this location. 416 mirror::ArtField* field = 417 verifier::MethodVerifier::FindAccessedFieldAtDexPc(throw_location.GetMethod(), 418 throw_location.GetDexPc()); 419 if (field != NULL) { 420 // NPE with precise message. 421 ThrowNullPointerExceptionForFieldAccess(throw_location, field, false /* write */); 422 } else { 423 // NPE with imprecise message. 424 ThrowNullPointerException(&throw_location, 425 "Attempt to write to a field on a null object reference"); 426 } 427 break; 428 } 429 case Instruction::AGET: 430 case Instruction::AGET_WIDE: 431 case Instruction::AGET_OBJECT: 432 case Instruction::AGET_BOOLEAN: 433 case Instruction::AGET_BYTE: 434 case Instruction::AGET_CHAR: 435 case Instruction::AGET_SHORT: 436 ThrowException(&throw_location, "Ljava/lang/NullPointerException;", NULL, 437 "Attempt to read from null array"); 438 break; 439 case Instruction::APUT: 440 case Instruction::APUT_WIDE: 441 case Instruction::APUT_OBJECT: 442 case Instruction::APUT_BOOLEAN: 443 case Instruction::APUT_BYTE: 444 case Instruction::APUT_CHAR: 445 case Instruction::APUT_SHORT: 446 ThrowException(&throw_location, "Ljava/lang/NullPointerException;", NULL, 447 "Attempt to write to null array"); 448 break; 449 case Instruction::ARRAY_LENGTH: 450 ThrowException(&throw_location, "Ljava/lang/NullPointerException;", NULL, 451 "Attempt to get length of null array"); 452 break; 453 default: { 454 // TODO: We should have covered all the cases where we expect a NPE above, this 455 // message/logging is so we can improve any cases we've missed in the future. 456 const DexFile& dex_file = 457 *throw_location.GetMethod()->GetDeclaringClass()->GetDexCache()->GetDexFile(); 458 ThrowException(&throw_location, "Ljava/lang/NullPointerException;", NULL, 459 StringPrintf("Null pointer exception during instruction '%s'", 460 instr->DumpString(&dex_file).c_str()).c_str()); 461 break; 462 } 463 } 464 } 465 466 void ThrowNullPointerException(const ThrowLocation* throw_location, const char* msg) { 467 ThrowException(throw_location, "Ljava/lang/NullPointerException;", NULL, msg); 468 } 469 470 // RuntimeException 471 472 void ThrowRuntimeException(const char* fmt, ...) { 473 va_list args; 474 va_start(args, fmt); 475 ThrowException(NULL, "Ljava/lang/RuntimeException;", NULL, fmt, &args); 476 va_end(args); 477 } 478 479 // VerifyError 480 481 void ThrowVerifyError(const mirror::Class* referrer, const char* fmt, ...) { 482 va_list args; 483 va_start(args, fmt); 484 ThrowException(NULL, "Ljava/lang/VerifyError;", referrer, fmt, &args); 485 va_end(args); 486 } 487 488 } // namespace art 489