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