Home | History | Annotate | Download | only in runtime
      1 /*
      2  * Copyright (C) 2011 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 "reflection-inl.h"
     18 
     19 #include "art_field-inl.h"
     20 #include "art_method-inl.h"
     21 #include "base/enums.h"
     22 #include "class_linker.h"
     23 #include "common_throws.h"
     24 #include "dex_file-inl.h"
     25 #include "indirect_reference_table-inl.h"
     26 #include "java_vm_ext.h"
     27 #include "jni_internal.h"
     28 #include "mirror/class-inl.h"
     29 #include "mirror/executable.h"
     30 #include "mirror/object_array-inl.h"
     31 #include "nth_caller_visitor.h"
     32 #include "scoped_thread_state_change-inl.h"
     33 #include "stack_reference.h"
     34 #include "well_known_classes.h"
     35 
     36 namespace art {
     37 
     38 using android::base::StringPrintf;
     39 
     40 class ArgArray {
     41  public:
     42   ArgArray(const char* shorty, uint32_t shorty_len)
     43       : shorty_(shorty), shorty_len_(shorty_len), num_bytes_(0) {
     44     size_t num_slots = shorty_len + 1;  // +1 in case of receiver.
     45     if (LIKELY((num_slots * 2) < kSmallArgArraySize)) {
     46       // We can trivially use the small arg array.
     47       arg_array_ = small_arg_array_;
     48     } else {
     49       // Analyze shorty to see if we need the large arg array.
     50       for (size_t i = 1; i < shorty_len; ++i) {
     51         char c = shorty[i];
     52         if (c == 'J' || c == 'D') {
     53           num_slots++;
     54         }
     55       }
     56       if (num_slots <= kSmallArgArraySize) {
     57         arg_array_ = small_arg_array_;
     58       } else {
     59         large_arg_array_.reset(new uint32_t[num_slots]);
     60         arg_array_ = large_arg_array_.get();
     61       }
     62     }
     63   }
     64 
     65   uint32_t* GetArray() {
     66     return arg_array_;
     67   }
     68 
     69   uint32_t GetNumBytes() {
     70     return num_bytes_;
     71   }
     72 
     73   void Append(uint32_t value) {
     74     arg_array_[num_bytes_ / 4] = value;
     75     num_bytes_ += 4;
     76   }
     77 
     78   void Append(ObjPtr<mirror::Object> obj) REQUIRES_SHARED(Locks::mutator_lock_) {
     79     Append(StackReference<mirror::Object>::FromMirrorPtr(obj.Ptr()).AsVRegValue());
     80   }
     81 
     82   void AppendWide(uint64_t value) {
     83     arg_array_[num_bytes_ / 4] = value;
     84     arg_array_[(num_bytes_ / 4) + 1] = value >> 32;
     85     num_bytes_ += 8;
     86   }
     87 
     88   void AppendFloat(float value) {
     89     jvalue jv;
     90     jv.f = value;
     91     Append(jv.i);
     92   }
     93 
     94   void AppendDouble(double value) {
     95     jvalue jv;
     96     jv.d = value;
     97     AppendWide(jv.j);
     98   }
     99 
    100   void BuildArgArrayFromVarArgs(const ScopedObjectAccessAlreadyRunnable& soa,
    101                                 ObjPtr<mirror::Object> receiver,
    102                                 va_list ap)
    103       REQUIRES_SHARED(Locks::mutator_lock_) {
    104     // Set receiver if non-null (method is not static)
    105     if (receiver != nullptr) {
    106       Append(receiver);
    107     }
    108     for (size_t i = 1; i < shorty_len_; ++i) {
    109       switch (shorty_[i]) {
    110         case 'Z':
    111         case 'B':
    112         case 'C':
    113         case 'S':
    114         case 'I':
    115           Append(va_arg(ap, jint));
    116           break;
    117         case 'F':
    118           AppendFloat(va_arg(ap, jdouble));
    119           break;
    120         case 'L':
    121           Append(soa.Decode<mirror::Object>(va_arg(ap, jobject)));
    122           break;
    123         case 'D':
    124           AppendDouble(va_arg(ap, jdouble));
    125           break;
    126         case 'J':
    127           AppendWide(va_arg(ap, jlong));
    128           break;
    129 #ifndef NDEBUG
    130         default:
    131           LOG(FATAL) << "Unexpected shorty character: " << shorty_[i];
    132 #endif
    133       }
    134     }
    135   }
    136 
    137   void BuildArgArrayFromJValues(const ScopedObjectAccessAlreadyRunnable& soa,
    138                                 ObjPtr<mirror::Object> receiver, jvalue* args)
    139       REQUIRES_SHARED(Locks::mutator_lock_) {
    140     // Set receiver if non-null (method is not static)
    141     if (receiver != nullptr) {
    142       Append(receiver);
    143     }
    144     for (size_t i = 1, args_offset = 0; i < shorty_len_; ++i, ++args_offset) {
    145       switch (shorty_[i]) {
    146         case 'Z':
    147           Append(args[args_offset].z);
    148           break;
    149         case 'B':
    150           Append(args[args_offset].b);
    151           break;
    152         case 'C':
    153           Append(args[args_offset].c);
    154           break;
    155         case 'S':
    156           Append(args[args_offset].s);
    157           break;
    158         case 'I':
    159         case 'F':
    160           Append(args[args_offset].i);
    161           break;
    162         case 'L':
    163           Append(soa.Decode<mirror::Object>(args[args_offset].l));
    164           break;
    165         case 'D':
    166         case 'J':
    167           AppendWide(args[args_offset].j);
    168           break;
    169 #ifndef NDEBUG
    170         default:
    171           LOG(FATAL) << "Unexpected shorty character: " << shorty_[i];
    172 #endif
    173       }
    174     }
    175   }
    176 
    177   void BuildArgArrayFromFrame(ShadowFrame* shadow_frame, uint32_t arg_offset)
    178       REQUIRES_SHARED(Locks::mutator_lock_) {
    179     // Set receiver if non-null (method is not static)
    180     size_t cur_arg = arg_offset;
    181     if (!shadow_frame->GetMethod()->IsStatic()) {
    182       Append(shadow_frame->GetVReg(cur_arg));
    183       cur_arg++;
    184     }
    185     for (size_t i = 1; i < shorty_len_; ++i) {
    186       switch (shorty_[i]) {
    187         case 'Z':
    188         case 'B':
    189         case 'C':
    190         case 'S':
    191         case 'I':
    192         case 'F':
    193         case 'L':
    194           Append(shadow_frame->GetVReg(cur_arg));
    195           cur_arg++;
    196           break;
    197         case 'D':
    198         case 'J':
    199           AppendWide(shadow_frame->GetVRegLong(cur_arg));
    200           cur_arg++;
    201           cur_arg++;
    202           break;
    203 #ifndef NDEBUG
    204         default:
    205           LOG(FATAL) << "Unexpected shorty character: " << shorty_[i];
    206 #endif
    207       }
    208     }
    209   }
    210 
    211   static void ThrowIllegalPrimitiveArgumentException(const char* expected,
    212                                                      const char* found_descriptor)
    213       REQUIRES_SHARED(Locks::mutator_lock_) {
    214     ThrowIllegalArgumentException(
    215         StringPrintf("Invalid primitive conversion from %s to %s", expected,
    216                      PrettyDescriptor(found_descriptor).c_str()).c_str());
    217   }
    218 
    219   bool BuildArgArrayFromObjectArray(ObjPtr<mirror::Object> receiver,
    220                                     ObjPtr<mirror::ObjectArray<mirror::Object>> raw_args,
    221                                     ArtMethod* m,
    222                                     Thread* self)
    223       REQUIRES_SHARED(Locks::mutator_lock_) {
    224     const DexFile::TypeList* classes = m->GetParameterTypeList();
    225     // Set receiver if non-null (method is not static)
    226     if (receiver != nullptr) {
    227       Append(receiver);
    228     }
    229     StackHandleScope<2> hs(self);
    230     MutableHandle<mirror::Object> arg(hs.NewHandle<mirror::Object>(nullptr));
    231     Handle<mirror::ObjectArray<mirror::Object>> args(
    232         hs.NewHandle<mirror::ObjectArray<mirror::Object>>(raw_args));
    233     for (size_t i = 1, args_offset = 0; i < shorty_len_; ++i, ++args_offset) {
    234       arg.Assign(args->Get(args_offset));
    235       if (((shorty_[i] == 'L') && (arg != nullptr)) ||
    236           ((arg == nullptr && shorty_[i] != 'L'))) {
    237         // TODO: The method's parameter's type must have been previously resolved, yet
    238         // we've seen cases where it's not b/34440020.
    239         ObjPtr<mirror::Class> dst_class(
    240             m->GetClassFromTypeIndex(classes->GetTypeItem(args_offset).type_idx_,
    241                                      true /* resolve */));
    242         if (dst_class.Ptr() == nullptr) {
    243           CHECK(self->IsExceptionPending());
    244           return false;
    245         }
    246         if (UNLIKELY(arg == nullptr || !arg->InstanceOf(dst_class))) {
    247           ThrowIllegalArgumentException(
    248               StringPrintf("method %s argument %zd has type %s, got %s",
    249                   m->PrettyMethod(false).c_str(),
    250                   args_offset + 1,  // Humans don't count from 0.
    251                   mirror::Class::PrettyDescriptor(dst_class).c_str(),
    252                   mirror::Object::PrettyTypeOf(arg.Get()).c_str()).c_str());
    253           return false;
    254         }
    255       }
    256 
    257 #define DO_FIRST_ARG(match_descriptor, get_fn, append) { \
    258           if (LIKELY(arg != nullptr && \
    259               arg->GetClass()->DescriptorEquals(match_descriptor))) { \
    260             ArtField* primitive_field = arg->GetClass()->GetInstanceField(0); \
    261             append(primitive_field-> get_fn(arg.Get()));
    262 
    263 #define DO_ARG(match_descriptor, get_fn, append) \
    264           } else if (LIKELY(arg != nullptr && \
    265                             arg->GetClass<>()->DescriptorEquals(match_descriptor))) { \
    266             ArtField* primitive_field = arg->GetClass()->GetInstanceField(0); \
    267             append(primitive_field-> get_fn(arg.Get()));
    268 
    269 #define DO_FAIL(expected) \
    270           } else { \
    271             if (arg->GetClass<>()->IsPrimitive()) { \
    272               std::string temp; \
    273               ThrowIllegalPrimitiveArgumentException(expected, \
    274                                                      arg->GetClass<>()->GetDescriptor(&temp)); \
    275             } else { \
    276               ThrowIllegalArgumentException(\
    277                   StringPrintf("method %s argument %zd has type %s, got %s", \
    278                       ArtMethod::PrettyMethod(m, false).c_str(), \
    279                       args_offset + 1, \
    280                       expected, \
    281                       mirror::Object::PrettyTypeOf(arg.Get()).c_str()).c_str()); \
    282             } \
    283             return false; \
    284           } }
    285 
    286       switch (shorty_[i]) {
    287         case 'L':
    288           Append(arg.Get());
    289           break;
    290         case 'Z':
    291           DO_FIRST_ARG("Ljava/lang/Boolean;", GetBoolean, Append)
    292           DO_FAIL("boolean")
    293           break;
    294         case 'B':
    295           DO_FIRST_ARG("Ljava/lang/Byte;", GetByte, Append)
    296           DO_FAIL("byte")
    297           break;
    298         case 'C':
    299           DO_FIRST_ARG("Ljava/lang/Character;", GetChar, Append)
    300           DO_FAIL("char")
    301           break;
    302         case 'S':
    303           DO_FIRST_ARG("Ljava/lang/Short;", GetShort, Append)
    304           DO_ARG("Ljava/lang/Byte;", GetByte, Append)
    305           DO_FAIL("short")
    306           break;
    307         case 'I':
    308           DO_FIRST_ARG("Ljava/lang/Integer;", GetInt, Append)
    309           DO_ARG("Ljava/lang/Character;", GetChar, Append)
    310           DO_ARG("Ljava/lang/Short;", GetShort, Append)
    311           DO_ARG("Ljava/lang/Byte;", GetByte, Append)
    312           DO_FAIL("int")
    313           break;
    314         case 'J':
    315           DO_FIRST_ARG("Ljava/lang/Long;", GetLong, AppendWide)
    316           DO_ARG("Ljava/lang/Integer;", GetInt, AppendWide)
    317           DO_ARG("Ljava/lang/Character;", GetChar, AppendWide)
    318           DO_ARG("Ljava/lang/Short;", GetShort, AppendWide)
    319           DO_ARG("Ljava/lang/Byte;", GetByte, AppendWide)
    320           DO_FAIL("long")
    321           break;
    322         case 'F':
    323           DO_FIRST_ARG("Ljava/lang/Float;", GetFloat, AppendFloat)
    324           DO_ARG("Ljava/lang/Long;", GetLong, AppendFloat)
    325           DO_ARG("Ljava/lang/Integer;", GetInt, AppendFloat)
    326           DO_ARG("Ljava/lang/Character;", GetChar, AppendFloat)
    327           DO_ARG("Ljava/lang/Short;", GetShort, AppendFloat)
    328           DO_ARG("Ljava/lang/Byte;", GetByte, AppendFloat)
    329           DO_FAIL("float")
    330           break;
    331         case 'D':
    332           DO_FIRST_ARG("Ljava/lang/Double;", GetDouble, AppendDouble)
    333           DO_ARG("Ljava/lang/Float;", GetFloat, AppendDouble)
    334           DO_ARG("Ljava/lang/Long;", GetLong, AppendDouble)
    335           DO_ARG("Ljava/lang/Integer;", GetInt, AppendDouble)
    336           DO_ARG("Ljava/lang/Character;", GetChar, AppendDouble)
    337           DO_ARG("Ljava/lang/Short;", GetShort, AppendDouble)
    338           DO_ARG("Ljava/lang/Byte;", GetByte, AppendDouble)
    339           DO_FAIL("double")
    340           break;
    341 #ifndef NDEBUG
    342         default:
    343           LOG(FATAL) << "Unexpected shorty character: " << shorty_[i];
    344           UNREACHABLE();
    345 #endif
    346       }
    347 #undef DO_FIRST_ARG
    348 #undef DO_ARG
    349 #undef DO_FAIL
    350     }
    351     return true;
    352   }
    353 
    354  private:
    355   enum { kSmallArgArraySize = 16 };
    356   const char* const shorty_;
    357   const uint32_t shorty_len_;
    358   uint32_t num_bytes_;
    359   uint32_t* arg_array_;
    360   uint32_t small_arg_array_[kSmallArgArraySize];
    361   std::unique_ptr<uint32_t[]> large_arg_array_;
    362 };
    363 
    364 static void CheckMethodArguments(JavaVMExt* vm, ArtMethod* m, uint32_t* args)
    365     REQUIRES_SHARED(Locks::mutator_lock_) {
    366   const DexFile::TypeList* params = m->GetParameterTypeList();
    367   if (params == nullptr) {
    368     return;  // No arguments so nothing to check.
    369   }
    370   uint32_t offset = 0;
    371   uint32_t num_params = params->Size();
    372   size_t error_count = 0;
    373   if (!m->IsStatic()) {
    374     offset = 1;
    375   }
    376   // TODO: If args contain object references, it may cause problems.
    377   Thread* const self = Thread::Current();
    378   for (uint32_t i = 0; i < num_params; i++) {
    379     dex::TypeIndex type_idx = params->GetTypeItem(i).type_idx_;
    380     ObjPtr<mirror::Class> param_type(m->GetClassFromTypeIndex(type_idx, true /* resolve */));
    381     if (param_type == nullptr) {
    382       CHECK(self->IsExceptionPending());
    383       LOG(ERROR) << "Internal error: unresolvable type for argument type in JNI invoke: "
    384           << m->GetTypeDescriptorFromTypeIdx(type_idx) << "\n"
    385           << self->GetException()->Dump();
    386       self->ClearException();
    387       ++error_count;
    388     } else if (!param_type->IsPrimitive()) {
    389       // TODO: There is a compaction bug here since GetClassFromTypeIdx can cause thread suspension,
    390       // this is a hard to fix problem since the args can contain Object*, we need to save and
    391       // restore them by using a visitor similar to the ones used in the trampoline entrypoints.
    392       ObjPtr<mirror::Object> argument =
    393           (reinterpret_cast<StackReference<mirror::Object>*>(&args[i + offset]))->AsMirrorPtr();
    394       if (argument != nullptr && !argument->InstanceOf(param_type)) {
    395         LOG(ERROR) << "JNI ERROR (app bug): attempt to pass an instance of "
    396                    << argument->PrettyTypeOf() << " as argument " << (i + 1)
    397                    << " to " << m->PrettyMethod();
    398         ++error_count;
    399       }
    400     } else if (param_type->IsPrimitiveLong() || param_type->IsPrimitiveDouble()) {
    401       offset++;
    402     } else {
    403       int32_t arg = static_cast<int32_t>(args[i + offset]);
    404       if (param_type->IsPrimitiveBoolean()) {
    405         if (arg != JNI_TRUE && arg != JNI_FALSE) {
    406           LOG(ERROR) << "JNI ERROR (app bug): expected jboolean (0/1) but got value of "
    407               << arg << " as argument " << (i + 1) << " to " << m->PrettyMethod();
    408           ++error_count;
    409         }
    410       } else if (param_type->IsPrimitiveByte()) {
    411         if (arg < -128 || arg > 127) {
    412           LOG(ERROR) << "JNI ERROR (app bug): expected jbyte but got value of "
    413               << arg << " as argument " << (i + 1) << " to " << m->PrettyMethod();
    414           ++error_count;
    415         }
    416       } else if (param_type->IsPrimitiveChar()) {
    417         if (args[i + offset] > 0xFFFF) {
    418           LOG(ERROR) << "JNI ERROR (app bug): expected jchar but got value of "
    419               << arg << " as argument " << (i + 1) << " to " << m->PrettyMethod();
    420           ++error_count;
    421         }
    422       } else if (param_type->IsPrimitiveShort()) {
    423         if (arg < -32768 || arg > 0x7FFF) {
    424           LOG(ERROR) << "JNI ERROR (app bug): expected jshort but got value of "
    425               << arg << " as argument " << (i + 1) << " to " << m->PrettyMethod();
    426           ++error_count;
    427         }
    428       }
    429     }
    430   }
    431   if (UNLIKELY(error_count > 0)) {
    432     // TODO: pass the JNI function name (such as "CallVoidMethodV") through so we can call JniAbort
    433     // with an argument.
    434     vm->JniAbortF(nullptr, "bad arguments passed to %s (see above for details)",
    435                   m->PrettyMethod().c_str());
    436   }
    437 }
    438 
    439 static ArtMethod* FindVirtualMethod(ObjPtr<mirror::Object> receiver, ArtMethod* method)
    440     REQUIRES_SHARED(Locks::mutator_lock_) {
    441   return receiver->GetClass()->FindVirtualMethodForVirtualOrInterface(method, kRuntimePointerSize);
    442 }
    443 
    444 
    445 static void InvokeWithArgArray(const ScopedObjectAccessAlreadyRunnable& soa,
    446                                ArtMethod* method, ArgArray* arg_array, JValue* result,
    447                                const char* shorty)
    448     REQUIRES_SHARED(Locks::mutator_lock_) {
    449   uint32_t* args = arg_array->GetArray();
    450   if (UNLIKELY(soa.Env()->check_jni)) {
    451     CheckMethodArguments(soa.Vm(), method->GetInterfaceMethodIfProxy(kRuntimePointerSize), args);
    452   }
    453   method->Invoke(soa.Self(), args, arg_array->GetNumBytes(), result, shorty);
    454 }
    455 
    456 JValue InvokeWithVarArgs(const ScopedObjectAccessAlreadyRunnable& soa, jobject obj, jmethodID mid,
    457                          va_list args)
    458     REQUIRES_SHARED(Locks::mutator_lock_) {
    459   // We want to make sure that the stack is not within a small distance from the
    460   // protected region in case we are calling into a leaf function whose stack
    461   // check has been elided.
    462   if (UNLIKELY(__builtin_frame_address(0) < soa.Self()->GetStackEnd())) {
    463     ThrowStackOverflowError(soa.Self());
    464     return JValue();
    465   }
    466 
    467   ArtMethod* method = jni::DecodeArtMethod(mid);
    468   bool is_string_init = method->GetDeclaringClass()->IsStringClass() && method->IsConstructor();
    469   if (is_string_init) {
    470     // Replace calls to String.<init> with equivalent StringFactory call.
    471     method = WellKnownClasses::StringInitToStringFactory(method);
    472   }
    473   ObjPtr<mirror::Object> receiver = method->IsStatic() ? nullptr : soa.Decode<mirror::Object>(obj);
    474   uint32_t shorty_len = 0;
    475   const char* shorty =
    476       method->GetInterfaceMethodIfProxy(kRuntimePointerSize)->GetShorty(&shorty_len);
    477   JValue result;
    478   ArgArray arg_array(shorty, shorty_len);
    479   arg_array.BuildArgArrayFromVarArgs(soa, receiver, args);
    480   InvokeWithArgArray(soa, method, &arg_array, &result, shorty);
    481   if (is_string_init) {
    482     // For string init, remap original receiver to StringFactory result.
    483     UpdateReference(soa.Self(), obj, result.GetL());
    484   }
    485   return result;
    486 }
    487 
    488 JValue InvokeWithJValues(const ScopedObjectAccessAlreadyRunnable& soa, jobject obj, jmethodID mid,
    489                          jvalue* args) {
    490   // We want to make sure that the stack is not within a small distance from the
    491   // protected region in case we are calling into a leaf function whose stack
    492   // check has been elided.
    493   if (UNLIKELY(__builtin_frame_address(0) < soa.Self()->GetStackEnd())) {
    494     ThrowStackOverflowError(soa.Self());
    495     return JValue();
    496   }
    497 
    498   ArtMethod* method = jni::DecodeArtMethod(mid);
    499   bool is_string_init = method->GetDeclaringClass()->IsStringClass() && method->IsConstructor();
    500   if (is_string_init) {
    501     // Replace calls to String.<init> with equivalent StringFactory call.
    502     method = WellKnownClasses::StringInitToStringFactory(method);
    503   }
    504   ObjPtr<mirror::Object> receiver = method->IsStatic() ? nullptr : soa.Decode<mirror::Object>(obj);
    505   uint32_t shorty_len = 0;
    506   const char* shorty =
    507       method->GetInterfaceMethodIfProxy(kRuntimePointerSize)->GetShorty(&shorty_len);
    508   JValue result;
    509   ArgArray arg_array(shorty, shorty_len);
    510   arg_array.BuildArgArrayFromJValues(soa, receiver, args);
    511   InvokeWithArgArray(soa, method, &arg_array, &result, shorty);
    512   if (is_string_init) {
    513     // For string init, remap original receiver to StringFactory result.
    514     UpdateReference(soa.Self(), obj, result.GetL());
    515   }
    516   return result;
    517 }
    518 
    519 JValue InvokeVirtualOrInterfaceWithJValues(const ScopedObjectAccessAlreadyRunnable& soa,
    520                                            jobject obj, jmethodID mid, jvalue* args) {
    521   // We want to make sure that the stack is not within a small distance from the
    522   // protected region in case we are calling into a leaf function whose stack
    523   // check has been elided.
    524   if (UNLIKELY(__builtin_frame_address(0) < soa.Self()->GetStackEnd())) {
    525     ThrowStackOverflowError(soa.Self());
    526     return JValue();
    527   }
    528 
    529   ObjPtr<mirror::Object> receiver = soa.Decode<mirror::Object>(obj);
    530   ArtMethod* method = FindVirtualMethod(receiver, jni::DecodeArtMethod(mid));
    531   bool is_string_init = method->GetDeclaringClass()->IsStringClass() && method->IsConstructor();
    532   if (is_string_init) {
    533     // Replace calls to String.<init> with equivalent StringFactory call.
    534     method = WellKnownClasses::StringInitToStringFactory(method);
    535     receiver = nullptr;
    536   }
    537   uint32_t shorty_len = 0;
    538   const char* shorty =
    539       method->GetInterfaceMethodIfProxy(kRuntimePointerSize)->GetShorty(&shorty_len);
    540   JValue result;
    541   ArgArray arg_array(shorty, shorty_len);
    542   arg_array.BuildArgArrayFromJValues(soa, receiver, args);
    543   InvokeWithArgArray(soa, method, &arg_array, &result, shorty);
    544   if (is_string_init) {
    545     // For string init, remap original receiver to StringFactory result.
    546     UpdateReference(soa.Self(), obj, result.GetL());
    547   }
    548   return result;
    549 }
    550 
    551 JValue InvokeVirtualOrInterfaceWithVarArgs(const ScopedObjectAccessAlreadyRunnable& soa,
    552                                            jobject obj, jmethodID mid, va_list args) {
    553   // We want to make sure that the stack is not within a small distance from the
    554   // protected region in case we are calling into a leaf function whose stack
    555   // check has been elided.
    556   if (UNLIKELY(__builtin_frame_address(0) < soa.Self()->GetStackEnd())) {
    557     ThrowStackOverflowError(soa.Self());
    558     return JValue();
    559   }
    560 
    561   ObjPtr<mirror::Object> receiver = soa.Decode<mirror::Object>(obj);
    562   ArtMethod* method = FindVirtualMethod(receiver, jni::DecodeArtMethod(mid));
    563   bool is_string_init = method->GetDeclaringClass()->IsStringClass() && method->IsConstructor();
    564   if (is_string_init) {
    565     // Replace calls to String.<init> with equivalent StringFactory call.
    566     method = WellKnownClasses::StringInitToStringFactory(method);
    567     receiver = nullptr;
    568   }
    569   uint32_t shorty_len = 0;
    570   const char* shorty =
    571       method->GetInterfaceMethodIfProxy(kRuntimePointerSize)->GetShorty(&shorty_len);
    572   JValue result;
    573   ArgArray arg_array(shorty, shorty_len);
    574   arg_array.BuildArgArrayFromVarArgs(soa, receiver, args);
    575   InvokeWithArgArray(soa, method, &arg_array, &result, shorty);
    576   if (is_string_init) {
    577     // For string init, remap original receiver to StringFactory result.
    578     UpdateReference(soa.Self(), obj, result.GetL());
    579   }
    580   return result;
    581 }
    582 
    583 jobject InvokeMethod(const ScopedObjectAccessAlreadyRunnable& soa, jobject javaMethod,
    584                      jobject javaReceiver, jobject javaArgs, size_t num_frames) {
    585   // We want to make sure that the stack is not within a small distance from the
    586   // protected region in case we are calling into a leaf function whose stack
    587   // check has been elided.
    588   if (UNLIKELY(__builtin_frame_address(0) <
    589                soa.Self()->GetStackEndForInterpreter(true))) {
    590     ThrowStackOverflowError(soa.Self());
    591     return nullptr;
    592   }
    593 
    594   ObjPtr<mirror::Executable> executable = soa.Decode<mirror::Executable>(javaMethod);
    595   const bool accessible = executable->IsAccessible();
    596   ArtMethod* m = executable->GetArtMethod();
    597 
    598   ObjPtr<mirror::Class> declaring_class = m->GetDeclaringClass();
    599   if (UNLIKELY(!declaring_class->IsInitialized())) {
    600     StackHandleScope<1> hs(soa.Self());
    601     HandleWrapperObjPtr<mirror::Class> h_class(hs.NewHandleWrapper(&declaring_class));
    602     if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(soa.Self(), h_class, true, true)) {
    603       return nullptr;
    604     }
    605   }
    606 
    607   ObjPtr<mirror::Object> receiver;
    608   if (!m->IsStatic()) {
    609     // Replace calls to String.<init> with equivalent StringFactory call.
    610     if (declaring_class->IsStringClass() && m->IsConstructor()) {
    611       m = WellKnownClasses::StringInitToStringFactory(m);
    612       CHECK(javaReceiver == nullptr);
    613     } else {
    614       // Check that the receiver is non-null and an instance of the field's declaring class.
    615       receiver = soa.Decode<mirror::Object>(javaReceiver);
    616       if (!VerifyObjectIsClass(receiver, declaring_class)) {
    617         return nullptr;
    618       }
    619 
    620       // Find the actual implementation of the virtual method.
    621       m = receiver->GetClass()->FindVirtualMethodForVirtualOrInterface(m, kRuntimePointerSize);
    622     }
    623   }
    624 
    625   // Get our arrays of arguments and their types, and check they're the same size.
    626   ObjPtr<mirror::ObjectArray<mirror::Object>> objects =
    627       soa.Decode<mirror::ObjectArray<mirror::Object>>(javaArgs);
    628   auto* np_method = m->GetInterfaceMethodIfProxy(kRuntimePointerSize);
    629   const DexFile::TypeList* classes = np_method->GetParameterTypeList();
    630   uint32_t classes_size = (classes == nullptr) ? 0 : classes->Size();
    631   uint32_t arg_count = (objects != nullptr) ? objects->GetLength() : 0;
    632   if (arg_count != classes_size) {
    633     ThrowIllegalArgumentException(StringPrintf("Wrong number of arguments; expected %d, got %d",
    634                                                classes_size, arg_count).c_str());
    635     return nullptr;
    636   }
    637 
    638   // If method is not set to be accessible, verify it can be accessed by the caller.
    639   ObjPtr<mirror::Class> calling_class;
    640   if (!accessible && !VerifyAccess(soa.Self(),
    641                                    receiver,
    642                                    declaring_class,
    643                                    m->GetAccessFlags(),
    644                                    &calling_class,
    645                                    num_frames)) {
    646     ThrowIllegalAccessException(
    647         StringPrintf("Class %s cannot access %s method %s of class %s",
    648             calling_class == nullptr ? "null" : calling_class->PrettyClass().c_str(),
    649             PrettyJavaAccessFlags(m->GetAccessFlags()).c_str(),
    650             m->PrettyMethod().c_str(),
    651             m->GetDeclaringClass() == nullptr ? "null" :
    652                 m->GetDeclaringClass()->PrettyClass().c_str()).c_str());
    653     return nullptr;
    654   }
    655 
    656   // Invoke the method.
    657   JValue result;
    658   uint32_t shorty_len = 0;
    659   const char* shorty = np_method->GetShorty(&shorty_len);
    660   ArgArray arg_array(shorty, shorty_len);
    661   if (!arg_array.BuildArgArrayFromObjectArray(receiver, objects, np_method, soa.Self())) {
    662     CHECK(soa.Self()->IsExceptionPending());
    663     return nullptr;
    664   }
    665 
    666   InvokeWithArgArray(soa, m, &arg_array, &result, shorty);
    667 
    668   // Wrap any exception with "Ljava/lang/reflect/InvocationTargetException;" and return early.
    669   if (soa.Self()->IsExceptionPending()) {
    670     // If we get another exception when we are trying to wrap, then just use that instead.
    671     jthrowable th = soa.Env()->ExceptionOccurred();
    672     soa.Self()->ClearException();
    673     jclass exception_class = soa.Env()->FindClass("java/lang/reflect/InvocationTargetException");
    674     if (exception_class == nullptr) {
    675       soa.Self()->AssertPendingException();
    676       return nullptr;
    677     }
    678     jmethodID mid = soa.Env()->GetMethodID(exception_class, "<init>", "(Ljava/lang/Throwable;)V");
    679     CHECK(mid != nullptr);
    680     jobject exception_instance = soa.Env()->NewObject(exception_class, mid, th);
    681     if (exception_instance == nullptr) {
    682       soa.Self()->AssertPendingException();
    683       return nullptr;
    684     }
    685     soa.Env()->Throw(reinterpret_cast<jthrowable>(exception_instance));
    686     return nullptr;
    687   }
    688 
    689   // Box if necessary and return.
    690   return soa.AddLocalReference<jobject>(BoxPrimitive(Primitive::GetType(shorty[0]), result));
    691 }
    692 
    693 ObjPtr<mirror::Object> BoxPrimitive(Primitive::Type src_class, const JValue& value) {
    694   if (src_class == Primitive::kPrimNot) {
    695     return MakeObjPtr(value.GetL());
    696   }
    697   if (src_class == Primitive::kPrimVoid) {
    698     // There's no such thing as a void field, and void methods invoked via reflection return null.
    699     return nullptr;
    700   }
    701 
    702   jmethodID m = nullptr;
    703   const char* shorty;
    704   switch (src_class) {
    705   case Primitive::kPrimBoolean:
    706     m = WellKnownClasses::java_lang_Boolean_valueOf;
    707     shorty = "LZ";
    708     break;
    709   case Primitive::kPrimByte:
    710     m = WellKnownClasses::java_lang_Byte_valueOf;
    711     shorty = "LB";
    712     break;
    713   case Primitive::kPrimChar:
    714     m = WellKnownClasses::java_lang_Character_valueOf;
    715     shorty = "LC";
    716     break;
    717   case Primitive::kPrimDouble:
    718     m = WellKnownClasses::java_lang_Double_valueOf;
    719     shorty = "LD";
    720     break;
    721   case Primitive::kPrimFloat:
    722     m = WellKnownClasses::java_lang_Float_valueOf;
    723     shorty = "LF";
    724     break;
    725   case Primitive::kPrimInt:
    726     m = WellKnownClasses::java_lang_Integer_valueOf;
    727     shorty = "LI";
    728     break;
    729   case Primitive::kPrimLong:
    730     m = WellKnownClasses::java_lang_Long_valueOf;
    731     shorty = "LJ";
    732     break;
    733   case Primitive::kPrimShort:
    734     m = WellKnownClasses::java_lang_Short_valueOf;
    735     shorty = "LS";
    736     break;
    737   default:
    738     LOG(FATAL) << static_cast<int>(src_class);
    739     shorty = nullptr;
    740   }
    741 
    742   ScopedObjectAccessUnchecked soa(Thread::Current());
    743   DCHECK_EQ(soa.Self()->GetState(), kRunnable);
    744 
    745   ArgArray arg_array(shorty, 2);
    746   JValue result;
    747   if (src_class == Primitive::kPrimDouble || src_class == Primitive::kPrimLong) {
    748     arg_array.AppendWide(value.GetJ());
    749   } else {
    750     arg_array.Append(value.GetI());
    751   }
    752 
    753   jni::DecodeArtMethod(m)->Invoke(soa.Self(),
    754                                   arg_array.GetArray(),
    755                                   arg_array.GetNumBytes(),
    756                                   &result,
    757                                   shorty);
    758   return result.GetL();
    759 }
    760 
    761 static std::string UnboxingFailureKind(ArtField* f)
    762     REQUIRES_SHARED(Locks::mutator_lock_) {
    763   if (f != nullptr) {
    764     return "field " + f->PrettyField(false);
    765   }
    766   return "result";
    767 }
    768 
    769 static bool UnboxPrimitive(ObjPtr<mirror::Object> o,
    770                            ObjPtr<mirror::Class> dst_class,
    771                            ArtField* f,
    772                            JValue* unboxed_value)
    773     REQUIRES_SHARED(Locks::mutator_lock_) {
    774   bool unbox_for_result = (f == nullptr);
    775   if (!dst_class->IsPrimitive()) {
    776     if (UNLIKELY(o != nullptr && !o->InstanceOf(dst_class))) {
    777       if (!unbox_for_result) {
    778         ThrowIllegalArgumentException(
    779             StringPrintf("%s has type %s, got %s",
    780                          UnboxingFailureKind(f).c_str(),
    781                          dst_class->PrettyDescriptor().c_str(),
    782                          o->PrettyTypeOf().c_str()).c_str());
    783       } else {
    784         ThrowClassCastException(
    785             StringPrintf("Couldn't convert result of type %s to %s",
    786                          o->PrettyTypeOf().c_str(),
    787                          dst_class->PrettyDescriptor().c_str()).c_str());
    788       }
    789       return false;
    790     }
    791     unboxed_value->SetL(o);
    792     return true;
    793   }
    794   if (UNLIKELY(dst_class->GetPrimitiveType() == Primitive::kPrimVoid)) {
    795     ThrowIllegalArgumentException(StringPrintf("Can't unbox %s to void",
    796                                                UnboxingFailureKind(f).c_str()).c_str());
    797     return false;
    798   }
    799   if (UNLIKELY(o == nullptr)) {
    800     if (!unbox_for_result) {
    801       ThrowIllegalArgumentException(
    802           StringPrintf("%s has type %s, got null",
    803                        UnboxingFailureKind(f).c_str(),
    804                        dst_class->PrettyDescriptor().c_str()).c_str());
    805     } else {
    806       ThrowNullPointerException(
    807           StringPrintf("Expected to unbox a '%s' primitive type but was returned null",
    808                        dst_class->PrettyDescriptor().c_str()).c_str());
    809     }
    810     return false;
    811   }
    812 
    813   JValue boxed_value;
    814   ObjPtr<mirror::Class> klass = o->GetClass();
    815   ObjPtr<mirror::Class> src_class = nullptr;
    816   ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
    817   ArtField* primitive_field = &klass->GetIFieldsPtr()->At(0);
    818   if (klass->DescriptorEquals("Ljava/lang/Boolean;")) {
    819     src_class = class_linker->FindPrimitiveClass('Z');
    820     boxed_value.SetZ(primitive_field->GetBoolean(o));
    821   } else if (klass->DescriptorEquals("Ljava/lang/Byte;")) {
    822     src_class = class_linker->FindPrimitiveClass('B');
    823     boxed_value.SetB(primitive_field->GetByte(o));
    824   } else if (klass->DescriptorEquals("Ljava/lang/Character;")) {
    825     src_class = class_linker->FindPrimitiveClass('C');
    826     boxed_value.SetC(primitive_field->GetChar(o));
    827   } else if (klass->DescriptorEquals("Ljava/lang/Float;")) {
    828     src_class = class_linker->FindPrimitiveClass('F');
    829     boxed_value.SetF(primitive_field->GetFloat(o));
    830   } else if (klass->DescriptorEquals("Ljava/lang/Double;")) {
    831     src_class = class_linker->FindPrimitiveClass('D');
    832     boxed_value.SetD(primitive_field->GetDouble(o));
    833   } else if (klass->DescriptorEquals("Ljava/lang/Integer;")) {
    834     src_class = class_linker->FindPrimitiveClass('I');
    835     boxed_value.SetI(primitive_field->GetInt(o));
    836   } else if (klass->DescriptorEquals("Ljava/lang/Long;")) {
    837     src_class = class_linker->FindPrimitiveClass('J');
    838     boxed_value.SetJ(primitive_field->GetLong(o));
    839   } else if (klass->DescriptorEquals("Ljava/lang/Short;")) {
    840     src_class = class_linker->FindPrimitiveClass('S');
    841     boxed_value.SetS(primitive_field->GetShort(o));
    842   } else {
    843     std::string temp;
    844     ThrowIllegalArgumentException(
    845         StringPrintf("%s has type %s, got %s", UnboxingFailureKind(f).c_str(),
    846             dst_class->PrettyDescriptor().c_str(),
    847             PrettyDescriptor(o->GetClass()->GetDescriptor(&temp)).c_str()).c_str());
    848     return false;
    849   }
    850 
    851   return ConvertPrimitiveValue(unbox_for_result,
    852                                src_class->GetPrimitiveType(), dst_class->GetPrimitiveType(),
    853                                boxed_value, unboxed_value);
    854 }
    855 
    856 bool UnboxPrimitiveForField(ObjPtr<mirror::Object> o,
    857                             ObjPtr<mirror::Class> dst_class,
    858                             ArtField* f,
    859                             JValue* unboxed_value) {
    860   DCHECK(f != nullptr);
    861   return UnboxPrimitive(o, dst_class, f, unboxed_value);
    862 }
    863 
    864 bool UnboxPrimitiveForResult(ObjPtr<mirror::Object> o,
    865                              ObjPtr<mirror::Class> dst_class,
    866                              JValue* unboxed_value) {
    867   return UnboxPrimitive(o, dst_class, nullptr, unboxed_value);
    868 }
    869 
    870 ObjPtr<mirror::Class> GetCallingClass(Thread* self, size_t num_frames) {
    871   NthCallerVisitor visitor(self, num_frames);
    872   visitor.WalkStack();
    873   return visitor.caller != nullptr ? visitor.caller->GetDeclaringClass() : nullptr;
    874 }
    875 
    876 bool VerifyAccess(Thread* self,
    877                   ObjPtr<mirror::Object> obj,
    878                   ObjPtr<mirror::Class> declaring_class,
    879                   uint32_t access_flags,
    880                   ObjPtr<mirror::Class>* calling_class,
    881                   size_t num_frames) {
    882   if ((access_flags & kAccPublic) != 0) {
    883     return true;
    884   }
    885   ObjPtr<mirror::Class> klass = GetCallingClass(self, num_frames);
    886   if (UNLIKELY(klass == nullptr)) {
    887     // The caller is an attached native thread.
    888     return false;
    889   }
    890   *calling_class = klass;
    891   return VerifyAccess(obj, declaring_class, access_flags, klass);
    892 }
    893 
    894 bool VerifyAccess(ObjPtr<mirror::Object> obj,
    895                   ObjPtr<mirror::Class> declaring_class,
    896                   uint32_t access_flags,
    897                   ObjPtr<mirror::Class> calling_class) {
    898   if (calling_class == declaring_class) {
    899     return true;
    900   }
    901   ScopedAssertNoThreadSuspension sants("verify-access");
    902   if ((access_flags & kAccPrivate) != 0) {
    903     return false;
    904   }
    905   if ((access_flags & kAccProtected) != 0) {
    906     if (obj != nullptr && !obj->InstanceOf(calling_class) &&
    907         !declaring_class->IsInSamePackage(calling_class)) {
    908       return false;
    909     } else if (declaring_class->IsAssignableFrom(calling_class)) {
    910       return true;
    911     }
    912   }
    913   return declaring_class->IsInSamePackage(calling_class);
    914 }
    915 
    916 void InvalidReceiverError(ObjPtr<mirror::Object> o, ObjPtr<mirror::Class> c) {
    917   std::string expected_class_name(mirror::Class::PrettyDescriptor(c));
    918   std::string actual_class_name(mirror::Object::PrettyTypeOf(o));
    919   ThrowIllegalArgumentException(StringPrintf("Expected receiver of type %s, but got %s",
    920                                              expected_class_name.c_str(),
    921                                              actual_class_name.c_str()).c_str());
    922 }
    923 
    924 // This only works if there's one reference which points to the object in obj.
    925 // Will need to be fixed if there's cases where it's not.
    926 void UpdateReference(Thread* self, jobject obj, ObjPtr<mirror::Object> result) {
    927   IndirectRef ref = reinterpret_cast<IndirectRef>(obj);
    928   IndirectRefKind kind = IndirectReferenceTable::GetIndirectRefKind(ref);
    929   if (kind == kLocal) {
    930     self->GetJniEnv()->locals.Update(obj, result);
    931   } else if (kind == kHandleScopeOrInvalid) {
    932     LOG(FATAL) << "Unsupported UpdateReference for kind kHandleScopeOrInvalid";
    933   } else if (kind == kGlobal) {
    934     self->GetJniEnv()->vm->UpdateGlobal(self, ref, result);
    935   } else {
    936     DCHECK_EQ(kind, kWeakGlobal);
    937     self->GetJniEnv()->vm->UpdateWeakGlobal(self, ref, result);
    938   }
    939 }
    940 
    941 }  // namespace art
    942