diff options
author | 2011-10-03 16:45:31 -0700 | |
---|---|---|
committer | 2011-10-03 16:45:31 -0700 | |
commit | f43f03a2ace71a6f45eb4861d77d6a4064ffd06f (patch) | |
tree | 17451ec1d0e04e4cc4d69b04321718eb2620af72 /src | |
parent | df59a25b4483d5810491ec5ff4274bfffb259bfd (diff) | |
parent | 6c8867daab4af4667e0e816f6beafa7c5d13e043 (diff) |
Merge "Implement artThrowVerificationErrorFromCode." into dalvik-dev
Diffstat (limited to 'src')
-rw-r--r-- | src/runtime_support.cc | 135 | ||||
-rw-r--r-- | src/runtime_support_asm.S | 2 | ||||
-rw-r--r-- | src/utils.cc | 4 | ||||
-rw-r--r-- | src/utils.h | 1 |
4 files changed, 134 insertions, 8 deletions
diff --git a/src/runtime_support.cc b/src/runtime_support.cc index ca1fdea0d1..57f216d461 100644 --- a/src/runtime_support.cc +++ b/src/runtime_support.cc @@ -16,6 +16,8 @@ #include "runtime_support.h" +#include "dex_verifier.h" + namespace art { // Temporary debugging hook for compiler. @@ -128,15 +130,136 @@ extern "C" void artThrowStackOverflowFromCode(Method* method, Thread* thread, Me thread->DeliverException(); } -extern "C" void artThrowVerificationErrorFromCode(int32_t src1, int32_t ref, Thread* thread, Method** sp) { +std::string ClassNameFromIndex(Method* method, uint32_t ref, DexVerifier::VerifyErrorRefType ref_type, bool access) { + ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); + const DexFile& dex_file = class_linker->FindDexFile(method->GetDeclaringClass()->GetDexCache()); + + uint16_t type_idx = 0; + if (ref_type == DexVerifier::VERIFY_ERROR_REF_FIELD) { + const DexFile::FieldId& id = dex_file.GetFieldId(ref); + type_idx = id.class_idx_; + } else if (ref_type == DexVerifier::VERIFY_ERROR_REF_METHOD) { + const DexFile::MethodId& id = dex_file.GetMethodId(ref); + type_idx = id.class_idx_; + } else if (ref_type == DexVerifier::VERIFY_ERROR_REF_CLASS) { + type_idx = ref; + } else { + CHECK(false) << static_cast<int>(ref_type); + } + + std::string class_name(PrettyDescriptor(dex_file.dexStringByTypeIdx(type_idx))); + if (!access) { + return class_name; + } + + std::string result; + result += "tried to access class "; + result += class_name; + result += " from class "; + result += PrettyDescriptor(method->GetDeclaringClass()->GetDescriptor()); + return result; +} + +std::string FieldNameFromIndex(const Method* method, uint32_t ref, DexVerifier::VerifyErrorRefType ref_type, bool access) { + CHECK_EQ(static_cast<int>(ref_type), static_cast<int>(DexVerifier::VERIFY_ERROR_REF_FIELD)); + + ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); + const DexFile& dex_file = class_linker->FindDexFile(method->GetDeclaringClass()->GetDexCache()); + + const DexFile::FieldId& id = dex_file.GetFieldId(ref); + std::string class_name(PrettyDescriptor(dex_file.dexStringByTypeIdx(id.class_idx_))); + const char* field_name = dex_file.dexStringById(id.name_idx_); + if (!access) { + return class_name + "." + field_name; + } + + std::string result; + result += "tried to access field "; + result += class_name + "." + field_name; + result += " from class "; + result += PrettyDescriptor(method->GetDeclaringClass()->GetDescriptor()); + return result; +} + +std::string MethodNameFromIndex(const Method* method, uint32_t ref, DexVerifier::VerifyErrorRefType ref_type, bool access) { + CHECK_EQ(static_cast<int>(ref_type), static_cast<int>(DexVerifier::VERIFY_ERROR_REF_METHOD)); + + ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); + const DexFile& dex_file = class_linker->FindDexFile(method->GetDeclaringClass()->GetDexCache()); + + const DexFile::MethodId& id = dex_file.GetMethodId(ref); + std::string class_name(PrettyDescriptor(dex_file.dexStringByTypeIdx(id.class_idx_))); + const char* method_name = dex_file.dexStringById(id.name_idx_); + if (!access) { + return class_name + "." + method_name; + } + + std::string result; + result += "tried to access method "; + result += class_name + "." + method_name + ":" + dex_file.CreateMethodDescriptor(id.proto_idx_, NULL); + result += " from class "; + result += PrettyDescriptor(method->GetDeclaringClass()->GetDescriptor()); + return result; +} + +extern "C" void artThrowVerificationErrorFromCode(int32_t kind, int32_t ref, Thread* self, Method** sp) { // Place a special frame at the TOS that will save all callee saves Runtime* runtime = Runtime::Current(); *sp = runtime->GetCalleeSaveMethod(); - thread->SetTopOfStack(sp, 0); - LOG(WARNING) << "TODO: verifcation error detail message. src1=" << src1 << " ref=" << ref; - thread->ThrowNewExceptionF("Ljava/lang/VerifyError;", - "TODO: verification error detail message. src1=%d; ref=%d", src1, ref); - thread->DeliverException(); + self->SetTopOfStack(sp, 0); + + Frame frame = self->GetTopOfStack(); + frame.Next(); + Method* method = frame.GetMethod(); + + DexVerifier::VerifyErrorRefType ref_type = static_cast<DexVerifier::VerifyErrorRefType>(kind >> kVerifyErrorRefTypeShift); + + const char* exception_class = "Ljava/lang/VerifyError;"; + std::string msg; + + switch (static_cast<DexVerifier::VerifyError>(kind & ~(0xff << kVerifyErrorRefTypeShift))) { + case DexVerifier::VERIFY_ERROR_NO_CLASS: + exception_class = "Ljava/lang/NoClassDefFoundError;"; + msg = ClassNameFromIndex(method, ref, ref_type, false); + break; + case DexVerifier::VERIFY_ERROR_NO_FIELD: + exception_class = "Ljava/lang/NoSuchFieldError;"; + msg = FieldNameFromIndex(method, ref, ref_type, false); + break; + case DexVerifier::VERIFY_ERROR_NO_METHOD: + exception_class = "Ljava/lang/NoSuchMethodError;"; + msg = MethodNameFromIndex(method, ref, ref_type, false); + break; + case DexVerifier::VERIFY_ERROR_ACCESS_CLASS: + exception_class = "Ljava/lang/IllegalAccessError;"; + msg = ClassNameFromIndex(method, ref, ref_type, true); + break; + case DexVerifier::VERIFY_ERROR_ACCESS_FIELD: + exception_class = "Ljava/lang/IllegalAccessError;"; + msg = FieldNameFromIndex(method, ref, ref_type, true); + break; + case DexVerifier::VERIFY_ERROR_ACCESS_METHOD: + exception_class = "Ljava/lang/IllegalAccessError;"; + msg = MethodNameFromIndex(method, ref, ref_type, true); + break; + case DexVerifier::VERIFY_ERROR_CLASS_CHANGE: + exception_class = "Ljava/lang/IncompatibleClassChangeError;"; + msg = ClassNameFromIndex(method, ref, ref_type, false); + break; + case DexVerifier::VERIFY_ERROR_INSTANTIATION: + exception_class = "Ljava/lang/InstantiationError;"; + msg = ClassNameFromIndex(method, ref, ref_type, false); + break; + case DexVerifier::VERIFY_ERROR_GENERIC: + // Generic VerifyError; use default exception, no message. + break; + case DexVerifier::VERIFY_ERROR_NONE: + CHECK(false); + break; + } + + self->ThrowNewException(exception_class, msg.c_str()); + self->DeliverException(); } extern "C" void artThrowInternalErrorFromCode(int32_t errnum, Thread* thread, Method** sp) { diff --git a/src/runtime_support_asm.S b/src/runtime_support_asm.S index dee8cc49e5..25a687266f 100644 --- a/src/runtime_support_asm.S +++ b/src/runtime_support_asm.S @@ -107,7 +107,7 @@ art_throw_verification_error_from_code: SETUP_CALLEE_SAVE_FRAME mov r2, r9 @ pass Thread::Current mov r3, sp @ pass SP - b artThrowVerificationErrorFromCode @ artThrowVerificationErrorFromCode(src1, ref, Thread*, SP) + b artThrowVerificationErrorFromCode @ artThrowVerificationErrorFromCode(kind, ref, Thread*, SP) .global art_invoke_interface_trampoline .extern artFindInterfaceMethodInCacheFromCode diff --git a/src/utils.cc b/src/utils.cc index b5063ffeb6..03a48114fc 100644 --- a/src/utils.cc +++ b/src/utils.cc @@ -51,8 +51,10 @@ std::string PrettyDescriptor(const String* java_descriptor) { if (java_descriptor == NULL) { return "null"; } - std::string descriptor(java_descriptor->ToModifiedUtf8()); + return PrettyDescriptor(java_descriptor->ToModifiedUtf8()); +} +std::string PrettyDescriptor(const std::string& descriptor) { // Count the number of '['s to get the dimensionality. const char* c = descriptor.c_str(); size_t dim = 0; diff --git a/src/utils.h b/src/utils.h index 97bf2c8202..5470f7f3d8 100644 --- a/src/utils.h +++ b/src/utils.h @@ -149,6 +149,7 @@ static inline std::string PrintableString(const StringT& s) { // "[[I" would be "int[][]", "[Ljava/lang/String;" would be // "java.lang.String[]", and so forth. std::string PrettyDescriptor(const String* descriptor); +std::string PrettyDescriptor(const std::string& descriptor); // Returns a human-readable signature for 'f'. Something like "a.b.C.f" or // "int a.b.C.f" (depending on the value of 'with_type'). |