Home | History | Annotate | Download | only in entrypoints
      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 "entrypoints/entrypoint_utils.h"
     18 
     19 #include "class_linker-inl.h"
     20 #include "dex_file-inl.h"
     21 #include "gc/accounting/card_table-inl.h"
     22 #include "mirror/art_field-inl.h"
     23 #include "mirror/art_method-inl.h"
     24 #include "mirror/class-inl.h"
     25 #include "mirror/object-inl.h"
     26 #include "object_utils.h"
     27 #include "mirror/object_array-inl.h"
     28 #include "mirror/proxy.h"
     29 #include "reflection.h"
     30 #include "scoped_thread_state_change.h"
     31 #include "ScopedLocalRef.h"
     32 #include "well_known_classes.h"
     33 
     34 namespace art {
     35 
     36 // Helper function to allocate array for FILLED_NEW_ARRAY.
     37 mirror::Array* CheckAndAllocArrayFromCode(uint32_t type_idx, mirror::ArtMethod* referrer,
     38                                           int32_t component_count, Thread* self,
     39                                           bool access_check) {
     40   if (UNLIKELY(component_count < 0)) {
     41     ThrowNegativeArraySizeException(component_count);
     42     return NULL;  // Failure
     43   }
     44   mirror::Class* klass = referrer->GetDexCacheResolvedTypes()->Get(type_idx);
     45   if (UNLIKELY(klass == NULL)) {  // Not in dex cache so try to resolve
     46     klass = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, referrer);
     47     if (klass == NULL) {  // Error
     48       DCHECK(self->IsExceptionPending());
     49       return NULL;  // Failure
     50     }
     51   }
     52   if (UNLIKELY(klass->IsPrimitive() && !klass->IsPrimitiveInt())) {
     53     if (klass->IsPrimitiveLong() || klass->IsPrimitiveDouble()) {
     54       ThrowRuntimeException("Bad filled array request for type %s",
     55                             PrettyDescriptor(klass).c_str());
     56     } else {
     57       ThrowLocation throw_location = self->GetCurrentLocationForThrow();
     58       DCHECK(throw_location.GetMethod() == referrer);
     59       self->ThrowNewExceptionF(throw_location, "Ljava/lang/InternalError;",
     60                                "Found type %s; filled-new-array not implemented for anything but \'int\'",
     61                                PrettyDescriptor(klass).c_str());
     62     }
     63     return NULL;  // Failure
     64   } else {
     65     if (access_check) {
     66       mirror::Class* referrer_klass = referrer->GetDeclaringClass();
     67       if (UNLIKELY(!referrer_klass->CanAccess(klass))) {
     68         ThrowIllegalAccessErrorClass(referrer_klass, klass);
     69         return NULL;  // Failure
     70       }
     71     }
     72     DCHECK(klass->IsArrayClass()) << PrettyClass(klass);
     73     return mirror::Array::Alloc(self, klass, component_count);
     74   }
     75 }
     76 
     77 mirror::ArtField* FindFieldFromCode(uint32_t field_idx, const mirror::ArtMethod* referrer,
     78                                  Thread* self, FindFieldType type, size_t expected_size,
     79                                  bool access_check) {
     80   bool is_primitive;
     81   bool is_set;
     82   bool is_static;
     83   switch (type) {
     84     case InstanceObjectRead:     is_primitive = false; is_set = false; is_static = false; break;
     85     case InstanceObjectWrite:    is_primitive = false; is_set = true;  is_static = false; break;
     86     case InstancePrimitiveRead:  is_primitive = true;  is_set = false; is_static = false; break;
     87     case InstancePrimitiveWrite: is_primitive = true;  is_set = true;  is_static = false; break;
     88     case StaticObjectRead:       is_primitive = false; is_set = false; is_static = true;  break;
     89     case StaticObjectWrite:      is_primitive = false; is_set = true;  is_static = true;  break;
     90     case StaticPrimitiveRead:    is_primitive = true;  is_set = false; is_static = true;  break;
     91     case StaticPrimitiveWrite:   // Keep GCC happy by having a default handler, fall-through.
     92     default:                     is_primitive = true;  is_set = true;  is_static = true;  break;
     93   }
     94   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
     95   mirror::ArtField* resolved_field = class_linker->ResolveField(field_idx, referrer, is_static);
     96   if (UNLIKELY(resolved_field == NULL)) {
     97     DCHECK(self->IsExceptionPending());  // Throw exception and unwind.
     98     return NULL;  // Failure.
     99   }
    100   mirror::Class* fields_class = resolved_field->GetDeclaringClass();
    101   if (access_check) {
    102     if (UNLIKELY(resolved_field->IsStatic() != is_static)) {
    103       ThrowIncompatibleClassChangeErrorField(resolved_field, is_static, referrer);
    104       return NULL;
    105     }
    106     mirror::Class* referring_class = referrer->GetDeclaringClass();
    107     if (UNLIKELY(!referring_class->CanAccess(fields_class) ||
    108                  !referring_class->CanAccessMember(fields_class,
    109                                                    resolved_field->GetAccessFlags()))) {
    110       // The referring class can't access the resolved field, this may occur as a result of a
    111       // protected field being made public by a sub-class. Resort to the dex file to determine
    112       // the correct class for the access check.
    113       const DexFile& dex_file = *referring_class->GetDexCache()->GetDexFile();
    114       fields_class = class_linker->ResolveType(dex_file,
    115                                                dex_file.GetFieldId(field_idx).class_idx_,
    116                                                referring_class);
    117       if (UNLIKELY(!referring_class->CanAccess(fields_class))) {
    118         ThrowIllegalAccessErrorClass(referring_class, fields_class);
    119         return NULL;  // failure
    120       } else if (UNLIKELY(!referring_class->CanAccessMember(fields_class,
    121                                                             resolved_field->GetAccessFlags()))) {
    122         ThrowIllegalAccessErrorField(referring_class, resolved_field);
    123         return NULL;  // failure
    124       }
    125     }
    126     if (UNLIKELY(is_set && resolved_field->IsFinal() && (fields_class != referring_class))) {
    127       ThrowIllegalAccessErrorFinalField(referrer, resolved_field);
    128       return NULL;  // failure
    129     } else {
    130       FieldHelper fh(resolved_field);
    131       if (UNLIKELY(fh.IsPrimitiveType() != is_primitive ||
    132                    fh.FieldSize() != expected_size)) {
    133         ThrowLocation throw_location = self->GetCurrentLocationForThrow();
    134         DCHECK(throw_location.GetMethod() == referrer);
    135         self->ThrowNewExceptionF(throw_location, "Ljava/lang/NoSuchFieldError;",
    136                                  "Attempted read of %zd-bit %s on field '%s'",
    137                                  expected_size * (32 / sizeof(int32_t)),
    138                                  is_primitive ? "primitive" : "non-primitive",
    139                                  PrettyField(resolved_field, true).c_str());
    140         return NULL;  // failure
    141       }
    142     }
    143   }
    144   if (!is_static) {
    145     // instance fields must be being accessed on an initialized class
    146     return resolved_field;
    147   } else {
    148     // If the class is initialized we're done.
    149     if (fields_class->IsInitialized()) {
    150       return resolved_field;
    151     } else if (Runtime::Current()->GetClassLinker()->EnsureInitialized(fields_class, true, true)) {
    152       // Otherwise let's ensure the class is initialized before resolving the field.
    153       return resolved_field;
    154     } else {
    155       DCHECK(self->IsExceptionPending());  // Throw exception and unwind
    156       return NULL;  // failure
    157     }
    158   }
    159 }
    160 
    161 // Slow path method resolution
    162 mirror::ArtMethod* FindMethodFromCode(uint32_t method_idx, mirror::Object* this_object,
    163                                            mirror::ArtMethod* referrer,
    164                                            Thread* self, bool access_check, InvokeType type) {
    165   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
    166   bool is_direct = type == kStatic || type == kDirect;
    167   mirror::ArtMethod* resolved_method = class_linker->ResolveMethod(method_idx, referrer, type);
    168   if (UNLIKELY(resolved_method == NULL)) {
    169     DCHECK(self->IsExceptionPending());  // Throw exception and unwind.
    170     return NULL;  // Failure.
    171   } else if (UNLIKELY(this_object == NULL && type != kStatic)) {
    172     // Maintain interpreter-like semantics where NullPointerException is thrown
    173     // after potential NoSuchMethodError from class linker.
    174     ThrowLocation throw_location = self->GetCurrentLocationForThrow();
    175     DCHECK(referrer == throw_location.GetMethod());
    176     ThrowNullPointerExceptionForMethodAccess(throw_location, method_idx, type);
    177     return NULL;  // Failure.
    178   } else {
    179     if (!access_check) {
    180       if (is_direct) {
    181         return resolved_method;
    182       } else if (type == kInterface) {
    183         mirror::ArtMethod* interface_method =
    184             this_object->GetClass()->FindVirtualMethodForInterface(resolved_method);
    185         if (UNLIKELY(interface_method == NULL)) {
    186           ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(resolved_method, this_object,
    187                                                                      referrer);
    188           return NULL;  // Failure.
    189         } else {
    190           return interface_method;
    191         }
    192       } else {
    193         mirror::ObjectArray<mirror::ArtMethod>* vtable;
    194         uint16_t vtable_index = resolved_method->GetMethodIndex();
    195         if (type == kSuper) {
    196           vtable = referrer->GetDeclaringClass()->GetSuperClass()->GetVTable();
    197         } else {
    198           vtable = this_object->GetClass()->GetVTable();
    199         }
    200         // TODO: eliminate bounds check?
    201         return vtable->Get(vtable_index);
    202       }
    203     } else {
    204       // Incompatible class change should have been handled in resolve method.
    205       if (UNLIKELY(resolved_method->CheckIncompatibleClassChange(type))) {
    206         ThrowIncompatibleClassChangeError(type, resolved_method->GetInvokeType(), resolved_method,
    207                                           referrer);
    208         return NULL;  // Failure.
    209       }
    210       mirror::Class* methods_class = resolved_method->GetDeclaringClass();
    211       mirror::Class* referring_class = referrer->GetDeclaringClass();
    212       if (UNLIKELY(!referring_class->CanAccess(methods_class) ||
    213                    !referring_class->CanAccessMember(methods_class,
    214                                                      resolved_method->GetAccessFlags()))) {
    215         // The referring class can't access the resolved method, this may occur as a result of a
    216         // protected method being made public by implementing an interface that re-declares the
    217         // method public. Resort to the dex file to determine the correct class for the access check
    218         const DexFile& dex_file = *referring_class->GetDexCache()->GetDexFile();
    219         methods_class = class_linker->ResolveType(dex_file,
    220                                                   dex_file.GetMethodId(method_idx).class_idx_,
    221                                                   referring_class);
    222         if (UNLIKELY(!referring_class->CanAccess(methods_class))) {
    223           ThrowIllegalAccessErrorClassForMethodDispatch(referring_class, methods_class,
    224                                                         referrer, resolved_method, type);
    225           return NULL;  // Failure.
    226         } else if (UNLIKELY(!referring_class->CanAccessMember(methods_class,
    227                                                               resolved_method->GetAccessFlags()))) {
    228           ThrowIllegalAccessErrorMethod(referring_class, resolved_method);
    229           return NULL;  // Failure.
    230         }
    231       }
    232       if (is_direct) {
    233         return resolved_method;
    234       } else if (type == kInterface) {
    235         mirror::ArtMethod* interface_method =
    236             this_object->GetClass()->FindVirtualMethodForInterface(resolved_method);
    237         if (UNLIKELY(interface_method == NULL)) {
    238           ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(resolved_method, this_object,
    239                                                                      referrer);
    240           return NULL;  // Failure.
    241         } else {
    242           return interface_method;
    243         }
    244       } else {
    245         mirror::ObjectArray<mirror::ArtMethod>* vtable;
    246         uint16_t vtable_index = resolved_method->GetMethodIndex();
    247         if (type == kSuper) {
    248           mirror::Class* super_class = referring_class->GetSuperClass();
    249           if (LIKELY(super_class != NULL)) {
    250             vtable = referring_class->GetSuperClass()->GetVTable();
    251           } else {
    252             vtable = NULL;
    253           }
    254         } else {
    255           vtable = this_object->GetClass()->GetVTable();
    256         }
    257         if (LIKELY(vtable != NULL &&
    258                    vtable_index < static_cast<uint32_t>(vtable->GetLength()))) {
    259           return vtable->GetWithoutChecks(vtable_index);
    260         } else {
    261           // Behavior to agree with that of the verifier.
    262           MethodHelper mh(resolved_method);
    263           ThrowNoSuchMethodError(type, resolved_method->GetDeclaringClass(), mh.GetName(),
    264                                  mh.GetSignature());
    265           return NULL;  // Failure.
    266         }
    267       }
    268     }
    269   }
    270 }
    271 
    272 void ThrowStackOverflowError(Thread* self) {
    273   if (self->IsHandlingStackOverflow()) {
    274       LOG(ERROR) << "Recursive stack overflow.";
    275       // We don't fail here because SetStackEndForStackOverflow will print better diagnostics.
    276   }
    277 
    278   if (Runtime::Current()->GetInstrumentation()->AreExitStubsInstalled()) {
    279     // Remove extra entry pushed onto second stack during method tracing.
    280     Runtime::Current()->GetInstrumentation()->PopMethodForUnwind(self, false);
    281   }
    282 
    283   self->SetStackEndForStackOverflow();  // Allow space on the stack for constructor to execute.
    284   JNIEnvExt* env = self->GetJniEnv();
    285   std::string msg("stack size ");
    286   msg += PrettySize(self->GetStackSize());
    287   // Use low-level JNI routine and pre-baked error class to avoid class linking operations that
    288   // would consume more stack.
    289   int rc = ::art::ThrowNewException(env, WellKnownClasses::java_lang_StackOverflowError,
    290                                     msg.c_str(), NULL);
    291   if (rc != JNI_OK) {
    292     // TODO: ThrowNewException failed presumably because of an OOME, we continue to throw the OOME
    293     //       or die in the CHECK below. We may want to throw a pre-baked StackOverflowError
    294     //       instead.
    295     LOG(ERROR) << "Couldn't throw new StackOverflowError because JNI ThrowNew failed.";
    296     CHECK(self->IsExceptionPending());
    297   }
    298   self->ResetDefaultStackEnd();  // Return to default stack size.
    299 }
    300 
    301 JValue InvokeProxyInvocationHandler(ScopedObjectAccessUnchecked& soa, const char* shorty,
    302                                     jobject rcvr_jobj, jobject interface_method_jobj,
    303                                     std::vector<jvalue>& args) {
    304   DCHECK(soa.Env()->IsInstanceOf(rcvr_jobj, WellKnownClasses::java_lang_reflect_Proxy));
    305 
    306   // Build argument array possibly triggering GC.
    307   soa.Self()->AssertThreadSuspensionIsAllowable();
    308   jobjectArray args_jobj = NULL;
    309   const JValue zero;
    310   if (args.size() > 0) {
    311     args_jobj = soa.Env()->NewObjectArray(args.size(), WellKnownClasses::java_lang_Object, NULL);
    312     if (args_jobj == NULL) {
    313       CHECK(soa.Self()->IsExceptionPending());
    314       return zero;
    315     }
    316     for (size_t i = 0; i < args.size(); ++i) {
    317       if (shorty[i + 1] == 'L') {
    318         jobject val = args.at(i).l;
    319         soa.Env()->SetObjectArrayElement(args_jobj, i, val);
    320       } else {
    321         JValue jv;
    322         jv.SetJ(args.at(i).j);
    323         mirror::Object* val = BoxPrimitive(Primitive::GetType(shorty[i + 1]), jv);
    324         if (val == NULL) {
    325           CHECK(soa.Self()->IsExceptionPending());
    326           return zero;
    327         }
    328         soa.Decode<mirror::ObjectArray<mirror::Object>* >(args_jobj)->Set(i, val);
    329       }
    330     }
    331   }
    332 
    333   // Call Proxy.invoke(Proxy proxy, ArtMethod method, Object[] args).
    334   jvalue invocation_args[3];
    335   invocation_args[0].l = rcvr_jobj;
    336   invocation_args[1].l = interface_method_jobj;
    337   invocation_args[2].l = args_jobj;
    338   jobject result =
    339       soa.Env()->CallStaticObjectMethodA(WellKnownClasses::java_lang_reflect_Proxy,
    340                                          WellKnownClasses::java_lang_reflect_Proxy_invoke,
    341                                          invocation_args);
    342 
    343   // Unbox result and handle error conditions.
    344   if (LIKELY(!soa.Self()->IsExceptionPending())) {
    345     if (shorty[0] == 'V' || (shorty[0] == 'L' && result == NULL)) {
    346       // Do nothing.
    347       return zero;
    348     } else {
    349       mirror::Object* result_ref = soa.Decode<mirror::Object*>(result);
    350       mirror::Object* rcvr = soa.Decode<mirror::Object*>(rcvr_jobj);
    351       mirror::ArtMethod* interface_method =
    352           soa.Decode<mirror::ArtMethod*>(interface_method_jobj);
    353       mirror::Class* result_type = MethodHelper(interface_method).GetReturnType();
    354       mirror::ArtMethod* proxy_method;
    355       if (interface_method->GetDeclaringClass()->IsInterface()) {
    356         proxy_method = rcvr->GetClass()->FindVirtualMethodForInterface(interface_method);
    357       } else {
    358         // Proxy dispatch to a method defined in Object.
    359         DCHECK(interface_method->GetDeclaringClass()->IsObjectClass());
    360         proxy_method = interface_method;
    361       }
    362       ThrowLocation throw_location(rcvr, proxy_method, -1);
    363       JValue result_unboxed;
    364       if (!UnboxPrimitiveForResult(throw_location, result_ref, result_type, result_unboxed)) {
    365         DCHECK(soa.Self()->IsExceptionPending());
    366         return zero;
    367       }
    368       return result_unboxed;
    369     }
    370   } else {
    371     // In the case of checked exceptions that aren't declared, the exception must be wrapped by
    372     // a UndeclaredThrowableException.
    373     mirror::Throwable* exception = soa.Self()->GetException(NULL);
    374     if (exception->IsCheckedException()) {
    375       mirror::Object* rcvr = soa.Decode<mirror::Object*>(rcvr_jobj);
    376       mirror::SynthesizedProxyClass* proxy_class =
    377           down_cast<mirror::SynthesizedProxyClass*>(rcvr->GetClass());
    378       mirror::ArtMethod* interface_method =
    379           soa.Decode<mirror::ArtMethod*>(interface_method_jobj);
    380       mirror::ArtMethod* proxy_method =
    381           rcvr->GetClass()->FindVirtualMethodForInterface(interface_method);
    382       int throws_index = -1;
    383       size_t num_virt_methods = proxy_class->NumVirtualMethods();
    384       for (size_t i = 0; i < num_virt_methods; i++) {
    385         if (proxy_class->GetVirtualMethod(i) == proxy_method) {
    386           throws_index = i;
    387           break;
    388         }
    389       }
    390       CHECK_NE(throws_index, -1);
    391       mirror::ObjectArray<mirror::Class>* declared_exceptions = proxy_class->GetThrows()->Get(throws_index);
    392       mirror::Class* exception_class = exception->GetClass();
    393       bool declares_exception = false;
    394       for (int i = 0; i < declared_exceptions->GetLength() && !declares_exception; i++) {
    395         mirror::Class* declared_exception = declared_exceptions->Get(i);
    396         declares_exception = declared_exception->IsAssignableFrom(exception_class);
    397       }
    398       if (!declares_exception) {
    399         ThrowLocation throw_location(rcvr, proxy_method, -1);
    400         soa.Self()->ThrowNewWrappedException(throw_location,
    401                                              "Ljava/lang/reflect/UndeclaredThrowableException;",
    402                                              NULL);
    403       }
    404     }
    405     return zero;
    406   }
    407 }
    408 
    409 }  // namespace art
    410