1a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes/* 2a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * Copyright (C) 2008 The Android Open Source Project 3a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * 4a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License"); 5a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * you may not use this file except in compliance with the License. 6a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * You may obtain a copy of the License at 7a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * 8a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * http://www.apache.org/licenses/LICENSE-2.0 9a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * 10a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * Unless required by applicable law or agreed to in writing, software 11a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS, 12a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * See the License for the specific language governing permissions and 14a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * limitations under the License. 15a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes */ 16a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 17a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#include "jni_internal.h" 18a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 19a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#include <sys/mman.h> 20a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#include <zlib.h> 21a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 2207ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include "base/logging.h" 23a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#include "class_linker.h" 242dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "class_linker-inl.h" 254f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "dex_file-inl.h" 2622d5e735f403c57525fe868304c7123f0ce66399Ian Rogers#include "field_helper.h" 271d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "gc/space/space.h" 28ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom#include "mirror/art_field-inl.h" 29ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom#include "mirror/art_method-inl.h" 302dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/class-inl.h" 312dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/object-inl.h" 322dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/object_array-inl.h" 33b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers#include "mirror/string-inl.h" 342dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/throwable.h" 3558df32711162823647356afe25ae2cde04133563Jeff Hao#include "runtime.h" 3600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#include "scoped_thread_state_change.h" 37a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#include "thread.h" 38a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 39a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughesnamespace art { 40a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 413f6635a2c84d645002f651c312d53f8348646c1fElliott Hughesstatic void JniAbort(const char* jni_function_name, const char* msg) { 42a09576416788b916095739e43a16917e7948f3a4Elliott Hughes Thread* self = Thread::Current(); 4300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccess soa(self); 44ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers mirror::ArtMethod* current_method = self->GetCurrentMethod(nullptr); 45a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 463b6baaa203fa63f1522b2172a1645f90412afdaeElliott Hughes std::ostringstream os; 473f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes os << "JNI DETECTED ERROR IN APPLICATION: " << msg; 48a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 49ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (jni_function_name != nullptr) { 503f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes os << "\n in call to " << jni_function_name; 51a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 52a09576416788b916095739e43a16917e7948f3a4Elliott Hughes // TODO: is this useful given that we're about to dump the calling thread's stack? 53ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (current_method != nullptr) { 543f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes os << "\n from " << PrettyMethod(current_method); 55a09576416788b916095739e43a16917e7948f3a4Elliott Hughes } 56a09576416788b916095739e43a16917e7948f3a4Elliott Hughes os << "\n"; 57a09576416788b916095739e43a16917e7948f3a4Elliott Hughes self->Dump(os); 58a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 59a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes JavaVMExt* vm = Runtime::Current()->GetJavaVM(); 60ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (vm->check_jni_abort_hook != nullptr) { 61b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes vm->check_jni_abort_hook(vm->check_jni_abort_hook_data, os.str()); 62a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } else { 639da7f59c9059397182b9a97e898a42ec06d4d646Ian Rogers // Ensure that we get a native stack trace for this thread. 649da7f59c9059397182b9a97e898a42ec06d4d646Ian Rogers self->TransitionFromRunnableToSuspended(kNative); 65a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes LOG(FATAL) << os.str(); 669da7f59c9059397182b9a97e898a42ec06d4d646Ian Rogers self->TransitionFromSuspendedToRunnable(); // Unreachable, keep annotalysis happy. 67a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 68a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes} 69a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 703f6635a2c84d645002f651c312d53f8348646c1fElliott Hughesstatic void JniAbortV(const char* jni_function_name, const char* fmt, va_list ap) { 713f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes std::string msg; 723f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes StringAppendV(&msg, fmt, ap); 733f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes JniAbort(jni_function_name, msg.c_str()); 743f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes} 753f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes 763f6635a2c84d645002f651c312d53f8348646c1fElliott Hughesvoid JniAbortF(const char* jni_function_name, const char* fmt, ...) { 773f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes va_list args; 783f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes va_start(args, fmt); 793f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes JniAbortV(jni_function_name, fmt, args); 803f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes va_end(args); 813f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes} 823f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes 83a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes/* 84a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * =========================================================================== 85a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * JNI function helpers 86a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * =========================================================================== 87a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes */ 88a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 89eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartierstatic bool IsHandleScopeLocalRef(JNIEnv* env, jobject localRef) { 90eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier return GetIndirectRefKind(localRef) == kHandleScopeOrInvalid && 91eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier reinterpret_cast<JNIEnvExt*>(env)->self->HandleScopeContains(localRef); 92959f8ed11ef9493a89b90a1f9a82a811dbc7ae0eIan Rogers} 93959f8ed11ef9493a89b90a1f9a82a811dbc7ae0eIan Rogers 943f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes// Flags passed into ScopedCheck. 95a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#define kFlag_Default 0x0000 96a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 973f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_CritBad 0x0000 // Calling while in critical is not allowed. 983f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_CritOkay 0x0001 // Calling while in critical is allowed. 993f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_CritGet 0x0002 // This is a critical "get". 1003f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_CritRelease 0x0003 // This is a critical "release". 1013f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_CritMask 0x0003 // Bit mask to get "crit" value. 102a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1033f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_ExcepBad 0x0000 // Raised exceptions are not allowed. 1043f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_ExcepOkay 0x0004 // Raised exceptions are allowed. 105a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1063f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_Release 0x0010 // Are we in a non-critical release function? 1073f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_NullableUtf 0x0020 // Are our UTF parameters nullable? 108a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1093f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes#define kFlag_Invocation 0x8000 // Part of the invocation interface (JavaVM*). 110a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 111485cac4fa028559f2a81802f7c9d02218ca93359Elliott Hughes#define kFlag_ForceTrace 0x80000000 // Add this to a JNI function's flags if you want to trace every call. 112485cac4fa028559f2a81802f7c9d02218ca93359Elliott Hughes 113a09576416788b916095739e43a16917e7948f3a4Elliott Hughesstatic const char* gBuiltInPrefixes[] = { 114a09576416788b916095739e43a16917e7948f3a4Elliott Hughes "Landroid/", 115a09576416788b916095739e43a16917e7948f3a4Elliott Hughes "Lcom/android/", 116a09576416788b916095739e43a16917e7948f3a4Elliott Hughes "Lcom/google/android/", 117a09576416788b916095739e43a16917e7948f3a4Elliott Hughes "Ldalvik/", 118a09576416788b916095739e43a16917e7948f3a4Elliott Hughes "Ljava/", 119a09576416788b916095739e43a16917e7948f3a4Elliott Hughes "Ljavax/", 120a09576416788b916095739e43a16917e7948f3a4Elliott Hughes "Llibcore/", 121a09576416788b916095739e43a16917e7948f3a4Elliott Hughes "Lorg/apache/harmony/", 122ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers nullptr 123a09576416788b916095739e43a16917e7948f3a4Elliott Hughes}; 124a09576416788b916095739e43a16917e7948f3a4Elliott Hughes 125ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogersstatic bool ShouldTrace(JavaVMExt* vm, mirror::ArtMethod* method) 126b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 127a09576416788b916095739e43a16917e7948f3a4Elliott Hughes // If both "-Xcheck:jni" and "-Xjnitrace:" are enabled, we print trace messages 128a09576416788b916095739e43a16917e7948f3a4Elliott Hughes // when a native method that matches the -Xjnitrace argument calls a JNI function 129a09576416788b916095739e43a16917e7948f3a4Elliott Hughes // such as NewByteArray. 130a09576416788b916095739e43a16917e7948f3a4Elliott Hughes // If -verbose:third-party-jni is on, we want to log any JNI function calls 131a09576416788b916095739e43a16917e7948f3a4Elliott Hughes // made by a third-party native method. 132bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier std::string class_name(method->GetDeclaringClassDescriptor()); 13381ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes if (!vm->trace.empty() && class_name.find(vm->trace) != std::string::npos) { 134a09576416788b916095739e43a16917e7948f3a4Elliott Hughes return true; 135a09576416788b916095739e43a16917e7948f3a4Elliott Hughes } 1364dd9b4d95eec9db5338fb9bf132f9bb8facf6cf4Elliott Hughes if (VLOG_IS_ON(third_party_jni)) { 137a09576416788b916095739e43a16917e7948f3a4Elliott Hughes // Return true if we're trying to log all third-party JNI activity and 'method' doesn't look 138a09576416788b916095739e43a16917e7948f3a4Elliott Hughes // like part of Android. 139ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers for (size_t i = 0; gBuiltInPrefixes[i] != nullptr; ++i) { 14081ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes if (StartsWith(class_name, gBuiltInPrefixes[i])) { 141a09576416788b916095739e43a16917e7948f3a4Elliott Hughes return false; 142a09576416788b916095739e43a16917e7948f3a4Elliott Hughes } 143a09576416788b916095739e43a16917e7948f3a4Elliott Hughes } 144a09576416788b916095739e43a16917e7948f3a4Elliott Hughes return true; 145a09576416788b916095739e43a16917e7948f3a4Elliott Hughes } 146a09576416788b916095739e43a16917e7948f3a4Elliott Hughes return false; 147a09576416788b916095739e43a16917e7948f3a4Elliott Hughes} 148a09576416788b916095739e43a16917e7948f3a4Elliott Hughes 149a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughesclass ScopedCheck { 150ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes public: 151a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes // For JNIEnv* functions. 15200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers explicit ScopedCheck(JNIEnv* env, int flags, const char* functionName) 153b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers SHARED_LOCK_FUNCTION(Locks::mutator_lock_) 15400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers : soa_(env) { 155365c10235438607541fa2259a5fec48061b90bd8Ian Rogers Init(flags, functionName, true); 15632ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes CheckThread(flags); 157a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 158a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 159a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes // For JavaVM* functions. 16000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // TODO: it's not correct that this is a lock function, but making it so aids annotalysis. 16100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers explicit ScopedCheck(JavaVM* vm, bool has_method, const char* functionName) 162b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers SHARED_LOCK_FUNCTION(Locks::mutator_lock_) 16300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers : soa_(vm) { 164365c10235438607541fa2259a5fec48061b90bd8Ian Rogers Init(kFlag_Invocation, functionName, has_method); 165a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 166a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 167b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers ~ScopedCheck() UNLOCK_FUNCTION(Locks::mutator_lock_) {} 16800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 16900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers const ScopedObjectAccess& soa() { 17000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers return soa_; 17100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 17200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 17332ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes bool ForceCopy() { 174a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return Runtime::Current()->GetJavaVM()->force_copy; 175a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 176a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 17781ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes // Checks that 'class_name' is a valid "fully-qualified" JNI class name, like "java/lang/Thread" 17881ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes // or "[Ljava/lang/Object;". A ClassLoader can actually normalize class names a couple of 17981ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes // times, so using "java.lang.Thread" instead of "java/lang/Thread" might work in some 18081ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes // circumstances, but this is incorrect. 18181ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes void CheckClassName(const char* class_name) { 1822d10b206f9d0b97396b7dadb9a6415cd39efd341Ian Rogers if ((class_name == nullptr) || !IsValidJniClassName(class_name)) { 1833f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes JniAbortF(function_name_, 1843f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes "illegal class name '%s'\n" 1853f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes " (should be of the form 'package/Class', [Lpackage/Class;' or '[[B')", 1863f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes class_name); 187a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 188a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 189a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 190a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes /* 191a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * Verify that the field is of the appropriate type. If the field has an 192a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * object type, "java_object" is the object we're trying to assign into it. 193a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * 194a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * Works for both static and instance fields. 195a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes */ 196ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers void CheckFieldType(jvalue value, jfieldID fid, char prim, bool isStatic) 197b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 19861c5ebc6aee2cac1c363de6fbdac25ada1697fdbMathieu Chartier StackHandleScope<1> hs(Thread::Current()); 19961c5ebc6aee2cac1c363de6fbdac25ada1697fdbMathieu Chartier Handle<mirror::ArtField> f(hs.NewHandle(CheckFieldID(fid))); 20061c5ebc6aee2cac1c363de6fbdac25ada1697fdbMathieu Chartier if (f.Get() == nullptr) { 201a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return; 202a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 2032dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Class* field_type = FieldHelper(f).GetType(); 2040cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers if (!field_type->IsPrimitive()) { 205ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers jobject java_object = value.l; 206ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (java_object != nullptr) { 2072dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Object* obj = soa_.Decode<mirror::Object*>(java_object); 2083f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes // If java_object is a weak global ref whose referent has been cleared, 2093f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes // obj will be NULL. Otherwise, obj should always be non-NULL 2103f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes // and valid. 211590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(obj)) { 212b76cac637691c29daa9c44e493b5bc26346ed116Mathieu Chartier Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR)); 2133f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes JniAbortF(function_name_, "field operation on invalid %s: %p", 2143f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(), java_object); 215a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return; 2160cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers } else { 217161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom if (!obj->InstanceOf(field_type)) { 2183f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes JniAbortF(function_name_, "attempt to set field %s with value of wrong type: %s", 21961c5ebc6aee2cac1c363de6fbdac25ada1697fdbMathieu Chartier PrettyField(f.Get()).c_str(), PrettyTypeOf(obj).c_str()); 2200cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers return; 2210cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers } 2220cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers } 223a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 2240cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers } else if (field_type != Runtime::Current()->GetClassLinker()->FindPrimitiveClass(prim)) { 2253f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes JniAbortF(function_name_, "attempt to set field %s with value of wrong type: %c", 22661c5ebc6aee2cac1c363de6fbdac25ada1697fdbMathieu Chartier PrettyField(f.Get()).c_str(), prim); 227a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return; 2280cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers } 2290cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers 23061c5ebc6aee2cac1c363de6fbdac25ada1697fdbMathieu Chartier if (isStatic != f.Get()->IsStatic()) { 231a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes if (isStatic) { 23261c5ebc6aee2cac1c363de6fbdac25ada1697fdbMathieu Chartier JniAbortF(function_name_, "accessing non-static field %s as static", 23361c5ebc6aee2cac1c363de6fbdac25ada1697fdbMathieu Chartier PrettyField(f.Get()).c_str()); 234a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } else { 23561c5ebc6aee2cac1c363de6fbdac25ada1697fdbMathieu Chartier JniAbortF(function_name_, "accessing static field %s as non-static", 23661c5ebc6aee2cac1c363de6fbdac25ada1697fdbMathieu Chartier PrettyField(f.Get()).c_str()); 237a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 238a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return; 239a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 240a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 241a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 242a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes /* 243a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * Verify that this instance field ID is valid for this object. 244a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * 245a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * Assumes "jobj" has already been validated. 246a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes */ 24700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void CheckInstanceFieldID(jobject java_object, jfieldID fid) 248b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 2492dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Object* o = soa_.Decode<mirror::Object*>(java_object); 250ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (o == nullptr || !Runtime::Current()->GetHeap()->IsValidObjectAddress(o)) { 251b76cac637691c29daa9c44e493b5bc26346ed116Mathieu Chartier Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR)); 2523f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes JniAbortF(function_name_, "field operation on invalid %s: %p", 2533f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(), java_object); 254a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return; 255a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 256a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 257ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtField* f = CheckFieldID(fid); 258ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (f == nullptr) { 25932ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes return; 26032ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes } 2612dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Class* c = o->GetClass(); 26261c5ebc6aee2cac1c363de6fbdac25ada1697fdbMathieu Chartier if (c->FindInstanceField(f->GetName(), f->GetTypeDescriptor()) == nullptr) { 2633f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes JniAbortF(function_name_, "jfieldID %s not valid for an object of class %s", 2643f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes PrettyField(f).c_str(), PrettyTypeOf(o).c_str()); 265a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 266a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 267a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 268a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes /* 269a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * Verify that the pointer value is non-NULL. 270a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes */ 27132ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes void CheckNonNull(const void* ptr) { 272ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (ptr == nullptr) { 2733f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes JniAbortF(function_name_, "non-nullable argument was NULL"); 274a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 275a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 276a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 277a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes /* 278a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * Verify that the method's return type matches the type of call. 279a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * 'expectedType' will be "L" for all objects, including arrays. 280a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes */ 28100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void CheckSig(jmethodID mid, const char* expectedType, bool isStatic) 282b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 283ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtMethod* m = CheckMethodID(mid); 284ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (m == nullptr) { 28532ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes return; 28632ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes } 287bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier if (*expectedType != m->GetShorty()[0]) { 2883f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes JniAbortF(function_name_, "the return type of %s does not match %s", 2893f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes function_name_, PrettyMethod(m).c_str()); 2903f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes } 2913f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes if (isStatic != m->IsStatic()) { 292a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes if (isStatic) { 2933f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes JniAbortF(function_name_, "calling non-static method %s with %s", 2943f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes PrettyMethod(m).c_str(), function_name_); 295a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } else { 2963f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes JniAbortF(function_name_, "calling static method %s with %s", 2973f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes PrettyMethod(m).c_str(), function_name_); 298a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 299a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 300a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 301a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 302a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes /* 303a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * Verify that this static field ID is valid for this class. 304a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * 305a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * Assumes "java_class" has already been validated. 306a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes */ 30700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void CheckStaticFieldID(jclass java_class, jfieldID fid) 308b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 3092dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Class* c = soa_.Decode<mirror::Class*>(java_class); 310ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers mirror::ArtField* f = CheckFieldID(fid); 311ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (f == nullptr) { 31232ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes return; 31332ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes } 314a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes if (f->GetDeclaringClass() != c) { 3153f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes JniAbortF(function_name_, "static jfieldID %p not valid for class %s", 3163f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes fid, PrettyClass(c).c_str()); 317a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 318a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 319a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 320a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes /* 321e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes * Verify that "mid" is appropriate for "java_class". 322a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * 323a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * A mismatch isn't dangerous, because the jmethodID defines the class. In 324e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes * fact, java_class is unused in the implementation. It's best if we don't 325a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * allow bad code in the system though. 326a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * 327e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes * Instances of "java_class" must be instances of the method's declaring class. 328a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes */ 32900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void CheckStaticMethod(jclass java_class, jmethodID mid) 330b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 331ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers mirror::ArtMethod* m = CheckMethodID(mid); 332ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (m == nullptr) { 33332ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes return; 33432ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes } 3352dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Class* c = soa_.Decode<mirror::Class*>(java_class); 33667fe2b41a6afccf6ab1a58879eae3e0e8f3d6c7aBrian Carlstrom if (!m->GetDeclaringClass()->IsAssignableFrom(c)) { 3373f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes JniAbortF(function_name_, "can't call static %s on class %s", 3383f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes PrettyMethod(m).c_str(), PrettyClass(c).c_str()); 339a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 340a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 341a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 342a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes /* 343a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * Verify that "mid" is appropriate for "jobj". 344a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * 345a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * Make sure the object is an instance of the method's declaring class. 346a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * (Note the mid might point to a declaration in an interface; this 347a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * will be handled automatically by the instanceof check.) 348a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes */ 34900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void CheckVirtualMethod(jobject java_object, jmethodID mid) 350b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 351ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers mirror::ArtMethod* m = CheckMethodID(mid); 352ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (m == nullptr) { 35332ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes return; 35432ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes } 3552dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Object* o = soa_.Decode<mirror::Object*>(java_object); 356167350d9c781c5e3893714bb26ab5cb1c4abf6b4Mathieu Chartier if (o == nullptr) { 357167350d9c781c5e3893714bb26ab5cb1c4abf6b4Mathieu Chartier JniAbortF(function_name_, "can't call %s on null object", PrettyMethod(m).c_str()); 358167350d9c781c5e3893714bb26ab5cb1c4abf6b4Mathieu Chartier } else if (!o->InstanceOf(m->GetDeclaringClass())) { 3593f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes JniAbortF(function_name_, "can't call %s on instance of %s", 3603f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes PrettyMethod(m).c_str(), PrettyTypeOf(o).c_str()); 361a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 362a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 363a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 364a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes /** 365a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * The format string is a sequence of the following characters, 366a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * and must be followed by arguments of the corresponding types 367a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * in the same order. 368a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * 369a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * Java primitive types: 370a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * B - jbyte 371a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * C - jchar 372a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * D - jdouble 373a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * F - jfloat 374a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * I - jint 375a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * J - jlong 376a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * S - jshort 377a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * Z - jboolean (shown as true and false) 378a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * V - void 379a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * 380a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * Java reference types: 381a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * L - jobject 382a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * a - jarray 383a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * c - jclass 384a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * s - jstring 385a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * 386a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * JNI types: 387a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * b - jboolean (shown as JNI_TRUE and JNI_FALSE) 388a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * f - jfieldID 389a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * m - jmethodID 390a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * p - void* 391a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * r - jint (for release mode arguments) 39278090d119d5e23ff35ecddac1f4a98e4c050bb07Elliott Hughes * u - const char* (Modified UTF-8) 393a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * z - jsize (for lengths; use i if negative values are okay) 394a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * v - JavaVM* 395a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * E - JNIEnv* 396a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * . - no argument; just print "..." (used for varargs JNI calls) 397a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * 398a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * Use the kFlag_NullableUtf flag where 'u' field(s) are nullable. 399a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes */ 400df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom void Check(bool entry, const char* fmt0, ...) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 401a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes va_list ap; 402a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 403ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers mirror::ArtMethod* traceMethod = nullptr; 4049365f5890eb27e1c98038ecf5a7fa2cad0aa62e6Ian Rogers if (has_method_ && (!soa_.Vm()->trace.empty() || VLOG_IS_ON(third_party_jni))) { 405a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes // We need to guard some of the invocation interface's calls: a bad caller might 406a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes // use DetachCurrentThread or GetEnv on a thread that's not yet attached. 407a09576416788b916095739e43a16917e7948f3a4Elliott Hughes Thread* self = Thread::Current(); 408ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if ((flags_ & kFlag_Invocation) == 0 || self != nullptr) { 409ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers traceMethod = self->GetCurrentMethod(nullptr); 410a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 411a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 412a09576416788b916095739e43a16917e7948f3a4Elliott Hughes 413ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (((flags_ & kFlag_ForceTrace) != 0) || 414ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers (traceMethod != nullptr && ShouldTrace(soa_.Vm(), traceMethod))) { 415a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes va_start(ap, fmt0); 416a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes std::string msg; 417a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes for (const char* fmt = fmt0; *fmt;) { 418a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes char ch = *fmt++; 4197934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom if (ch == 'B') { // jbyte 420a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes jbyte b = va_arg(ap, int); 421a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes if (b >= 0 && b < 10) { 422a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes StringAppendF(&msg, "%d", b); 423a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } else { 424a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes StringAppendF(&msg, "%#x (%d)", b, b); 425a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 4267934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom } else if (ch == 'C') { // jchar 427a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes jchar c = va_arg(ap, int); 428a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes if (c < 0x7f && c >= ' ') { 429a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes StringAppendF(&msg, "U+%x ('%c')", c, c); 430a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } else { 431a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes StringAppendF(&msg, "U+%x", c); 432a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 4337934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom } else if (ch == 'F' || ch == 'D') { // jfloat, jdouble 434a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes StringAppendF(&msg, "%g", va_arg(ap, double)); 4357934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom } else if (ch == 'I' || ch == 'S') { // jint, jshort 436a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes StringAppendF(&msg, "%d", va_arg(ap, int)); 4377934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom } else if (ch == 'J') { // jlong 438ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers StringAppendF(&msg, "%" PRId64, va_arg(ap, jlong)); 4397934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom } else if (ch == 'Z') { // jboolean 440a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes StringAppendF(&msg, "%s", va_arg(ap, int) ? "true" : "false"); 4417934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom } else if (ch == 'V') { // void 442a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes msg += "void"; 4437934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom } else if (ch == 'v') { // JavaVM* 444a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes JavaVM* vm = va_arg(ap, JavaVM*); 445a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes StringAppendF(&msg, "(JavaVM*)%p", vm); 4467934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom } else if (ch == 'E') { // JNIEnv* 447a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes JNIEnv* env = va_arg(ap, JNIEnv*); 448a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes StringAppendF(&msg, "(JNIEnv*)%p", env); 4497934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom } else if (ch == 'L' || ch == 'a' || ch == 's') { // jobject, jarray, jstring 450a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes // For logging purposes, these are identical. 451a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes jobject o = va_arg(ap, jobject); 452ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (o == nullptr) { 453a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes msg += "NULL"; 454a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } else { 455a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes StringAppendF(&msg, "%p", o); 456a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 4577934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom } else if (ch == 'b') { // jboolean (JNI-style) 458a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes jboolean b = va_arg(ap, int); 459a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes msg += (b ? "JNI_TRUE" : "JNI_FALSE"); 4607934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom } else if (ch == 'c') { // jclass 461a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes jclass jc = va_arg(ap, jclass); 4622dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Class* c = reinterpret_cast<mirror::Class*>(Thread::Current()->DecodeJObject(jc)); 463ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (c == nullptr) { 464a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes msg += "NULL"; 465590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier } else if (c == kInvalidIndirectRefObject || 466590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier !Runtime::Current()->GetHeap()->IsValidObjectAddress(c)) { 467485cac4fa028559f2a81802f7c9d02218ca93359Elliott Hughes StringAppendF(&msg, "INVALID POINTER:%p", jc); 468485cac4fa028559f2a81802f7c9d02218ca93359Elliott Hughes } else if (!c->IsClass()) { 469485cac4fa028559f2a81802f7c9d02218ca93359Elliott Hughes msg += "INVALID NON-CLASS OBJECT OF TYPE:" + PrettyTypeOf(c); 470a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } else { 47154e7df1896a4066cbb9fe6f72249829f0b8c49c6Elliott Hughes msg += PrettyClass(c); 472a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes if (!entry) { 473a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes StringAppendF(&msg, " (%p)", jc); 474a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 475a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 4767934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom } else if (ch == 'f') { // jfieldID 477a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes jfieldID fid = va_arg(ap, jfieldID); 478ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtField* f = reinterpret_cast<mirror::ArtField*>(fid); 479a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes msg += PrettyField(f); 480a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes if (!entry) { 481a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes StringAppendF(&msg, " (%p)", fid); 482a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 4837934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom } else if (ch == 'z') { // non-negative jsize 484a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes // You might expect jsize to be size_t, but it's not; it's the same as jint. 485a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes // We only treat this specially so we can do the non-negative check. 486a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes // TODO: maybe this wasn't worth it? 487a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes jint i = va_arg(ap, jint); 488a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes StringAppendF(&msg, "%d", i); 4897934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom } else if (ch == 'm') { // jmethodID 490a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes jmethodID mid = va_arg(ap, jmethodID); 491ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtMethod* m = reinterpret_cast<mirror::ArtMethod*>(mid); 492a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes msg += PrettyMethod(m); 493a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes if (!entry) { 494a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes StringAppendF(&msg, " (%p)", mid); 495a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 4967934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom } else if (ch == 'p') { // void* ("pointer") 497a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes void* p = va_arg(ap, void*); 498ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (p == nullptr) { 499a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes msg += "NULL"; 500a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } else { 501a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes StringAppendF(&msg, "(void*) %p", p); 502a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 5037934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom } else if (ch == 'r') { // jint (release mode) 504a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes jint releaseMode = va_arg(ap, jint); 505a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes if (releaseMode == 0) { 506a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes msg += "0"; 507a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } else if (releaseMode == JNI_ABORT) { 508a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes msg += "JNI_ABORT"; 509a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } else if (releaseMode == JNI_COMMIT) { 510a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes msg += "JNI_COMMIT"; 511a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } else { 512a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes StringAppendF(&msg, "invalid release mode %d", releaseMode); 513a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 5147934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom } else if (ch == 'u') { // const char* (Modified UTF-8) 515a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes const char* utf = va_arg(ap, const char*); 516ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (utf == nullptr) { 517a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes msg += "NULL"; 518a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } else { 519a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes StringAppendF(&msg, "\"%s\"", utf); 520a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 521a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } else if (ch == '.') { 522a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes msg += "..."; 523a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } else { 5243f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes JniAbortF(function_name_, "unknown trace format specifier: %c", ch); 525a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return; 526a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 527a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes if (*fmt) { 528a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes StringAppendF(&msg, ", "); 529a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 530a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 531a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes va_end(ap); 532a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 533485cac4fa028559f2a81802f7c9d02218ca93359Elliott Hughes if ((flags_ & kFlag_ForceTrace) != 0) { 534485cac4fa028559f2a81802f7c9d02218ca93359Elliott Hughes LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")"; 535485cac4fa028559f2a81802f7c9d02218ca93359Elliott Hughes } else if (entry) { 53632ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes if (has_method_) { 537a09576416788b916095739e43a16917e7948f3a4Elliott Hughes std::string methodName(PrettyMethod(traceMethod, false)); 53832ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")"; 53932ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes indent_ = methodName.size() + 1; 540a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } else { 54132ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")"; 54232ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes indent_ = 0; 543a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 544a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } else { 54532ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str()); 546a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 547a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 548a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 549a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes // We always do the thorough checks on entry, and never on exit... 550a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes if (entry) { 551a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes va_start(ap, fmt0); 552a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes for (const char* fmt = fmt0; *fmt; ++fmt) { 553a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes char ch = *fmt; 554a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes if (ch == 'a') { 55532ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes CheckArray(va_arg(ap, jarray)); 556a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } else if (ch == 'c') { 55732ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes CheckInstance(kClass, va_arg(ap, jclass)); 558a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } else if (ch == 'L') { 55932ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes CheckObject(va_arg(ap, jobject)); 560a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } else if (ch == 'r') { 56132ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes CheckReleaseMode(va_arg(ap, jint)); 562a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } else if (ch == 's') { 56332ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes CheckInstance(kString, va_arg(ap, jstring)); 564a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } else if (ch == 'u') { 56532ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes if ((flags_ & kFlag_Release) != 0) { 56632ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes CheckNonNull(va_arg(ap, const char*)); 567a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } else { 56832ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes bool nullable = ((flags_ & kFlag_NullableUtf) != 0); 56932ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes CheckUtfString(va_arg(ap, const char*), nullable); 570a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 571a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } else if (ch == 'z') { 57232ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes CheckLengthPositive(va_arg(ap, jsize)); 573ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers } else if (strchr("BCISZbfmpEv", ch) != nullptr) { 5747934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom va_arg(ap, uint32_t); // Skip this argument. 575a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } else if (ch == 'D' || ch == 'F') { 5767934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom va_arg(ap, double); // Skip this argument. 577a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } else if (ch == 'J') { 5787934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom va_arg(ap, uint64_t); // Skip this argument. 579a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } else if (ch == '.') { 580a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } else { 5813d30d9b09c16542d41554aad9f46ec9109ba5cb5Elliott Hughes LOG(FATAL) << "Unknown check format specifier: " << ch; 582a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 583a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 584a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes va_end(ap); 585a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 586a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 587a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 588a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes enum InstanceKind { 589a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes kClass, 5900f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes kDirectByteBuffer, 5910f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes kObject, 5920f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes kString, 5930f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes kThrowable, 594a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes }; 595a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes 596a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes /* 597a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes * Verify that "jobj" is a valid non-NULL object reference, and points to 598a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes * an instance of expectedClass. 599a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes * 600a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes * Because we're looking at an object on the GC heap, we have to switch 601a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes * to "running" mode before doing the checks. 602a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes */ 60300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers bool CheckInstance(InstanceKind kind, jobject java_object) 604b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 605ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers const char* what = nullptr; 606a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes switch (kind) { 607a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes case kClass: 608a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes what = "jclass"; 609a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes break; 610a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes case kDirectByteBuffer: 611a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes what = "direct ByteBuffer"; 612a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes break; 613a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes case kObject: 614a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes what = "jobject"; 615a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes break; 616a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes case kString: 617a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes what = "jstring"; 618a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes break; 619a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes case kThrowable: 620a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes what = "jthrowable"; 621a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes break; 622a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes default: 6237b9d996e4cd7d154bb1a244d67139aff0c363cf2Elliott Hughes LOG(FATAL) << "Unknown kind " << static_cast<int>(kind); 624a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes } 625a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes 626ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (java_object == nullptr) { 6273f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes JniAbortF(function_name_, "%s received null %s", function_name_, what); 628a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes return false; 629a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes } 630a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes 6312dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Object* obj = soa_.Decode<mirror::Object*>(java_object); 632590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(obj)) { 633b76cac637691c29daa9c44e493b5bc26346ed116Mathieu Chartier Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR)); 6343f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes JniAbortF(function_name_, "%s is an invalid %s: %p (%p)", 6353f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes what, ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(), java_object, obj); 636a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes return false; 637a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes } 638a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes 639a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes bool okay = true; 640a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes switch (kind) { 641a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes case kClass: 642a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes okay = obj->IsClass(); 643a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes break; 644a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes case kDirectByteBuffer: 645a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes UNIMPLEMENTED(FATAL); 646a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes break; 647a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes case kString: 648a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes okay = obj->GetClass()->IsStringClass(); 649a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes break; 650a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes case kThrowable: 651a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes okay = obj->GetClass()->IsThrowableClass(); 652a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes break; 653a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes case kObject: 654a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes break; 655a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes } 656a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes if (!okay) { 6573f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes JniAbortF(function_name_, "%s has wrong type: %s", what, PrettyTypeOf(obj).c_str()); 658a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes return false; 659a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes } 660a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes 661a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes return true; 662a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes } 663a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes 664ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes private: 66581ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes // Set "has_method" to true if we have a valid thread with a method pointer. 66681ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes // We won't have one before attaching a thread, after detaching a thread, or 66781ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes // when shutting down the runtime. 668365c10235438607541fa2259a5fec48061b90bd8Ian Rogers void Init(int flags, const char* functionName, bool has_method) { 66932ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes flags_ = flags; 67032ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes function_name_ = functionName; 67181ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes has_method_ = has_method; 672a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 673a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 674a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes /* 675a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * Verify that "array" is non-NULL and points to an Array object. 676a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * 677a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * Since we're dealing with objects, switch to "running" mode. 678a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes */ 679b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers void CheckArray(jarray java_array) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 680ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (java_array == nullptr) { 6813f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes JniAbortF(function_name_, "jarray was NULL"); 682a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return; 683a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 684a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 6852dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Array* a = soa_.Decode<mirror::Array*>(java_array); 686590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(a)) { 687b76cac637691c29daa9c44e493b5bc26346ed116Mathieu Chartier Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR)); 6883f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes JniAbortF(function_name_, "jarray is an invalid %s: %p (%p)", 6893f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes ToStr<IndirectRefKind>(GetIndirectRefKind(java_array)).c_str(), java_array, a); 690a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } else if (!a->IsArrayInstance()) { 6913f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes JniAbortF(function_name_, "jarray argument has non-array type: %s", PrettyTypeOf(a).c_str()); 692a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 693a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 694a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 69532ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes void CheckLengthPositive(jsize length) { 696a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes if (length < 0) { 6973f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes JniAbortF(function_name_, "negative jsize: %d", length); 698a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 699a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 700a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 701ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtField* CheckFieldID(jfieldID fid) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 702ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (fid == nullptr) { 7033f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes JniAbortF(function_name_, "jfieldID was NULL"); 704ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers return nullptr; 70532ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes } 706ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtField* f = soa_.DecodeField(fid); 707590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(f) || !f->IsArtField()) { 708b76cac637691c29daa9c44e493b5bc26346ed116Mathieu Chartier Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR)); 7093f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes JniAbortF(function_name_, "invalid jfieldID: %p", fid); 710ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers return nullptr; 71132ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes } 71232ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes return f; 71332ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes } 71432ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes 715ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtMethod* CheckMethodID(jmethodID mid) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 716ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (mid == nullptr) { 7173f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes JniAbortF(function_name_, "jmethodID was NULL"); 718ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers return nullptr; 71932ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes } 720ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom mirror::ArtMethod* m = soa_.DecodeMethod(mid); 721590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(m) || !m->IsArtMethod()) { 722b76cac637691c29daa9c44e493b5bc26346ed116Mathieu Chartier Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR)); 7233f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes JniAbortF(function_name_, "invalid jmethodID: %p", mid); 724ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers return nullptr; 72532ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes } 72632ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes return m; 72732ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes } 72832ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes 729a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes /* 730a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * Verify that "jobj" is a valid object, and that it's an object that JNI 731a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * is allowed to know about. We allow NULL references. 732a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * 733a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * Switches to "running" mode before performing checks. 734a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes */ 73500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers void CheckObject(jobject java_object) 736b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 737ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (java_object == nullptr) { 738a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return; 739a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 740a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 7412dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Object* o = soa_.Decode<mirror::Object*>(java_object); 742590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(o)) { 743b76cac637691c29daa9c44e493b5bc26346ed116Mathieu Chartier Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR)); 744c5bfa8f49d8548d7c685a99b411311ef56bedffaElliott Hughes // TODO: when we remove work_around_app_jni_bugs, this should be impossible. 7453f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes JniAbortF(function_name_, "native code passing in reference to invalid %s: %p", 7463f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(), java_object); 747a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 748a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 749a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 750a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes /* 751a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * Verify that the "mode" argument passed to a primitive array Release 752a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * function is one of the valid values. 753a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes */ 75432ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes void CheckReleaseMode(jint mode) { 755a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes if (mode != 0 && mode != JNI_COMMIT && mode != JNI_ABORT) { 75696a9887f0bc912661e0a7478c7eb19847d2e2e06Elliott Hughes JniAbortF(function_name_, "unknown value for release mode: %d", mode); 757a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 758a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 759a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 760b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers void CheckThread(int flags) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 761a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes Thread* self = Thread::Current(); 762ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (self == nullptr) { 7633f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes JniAbortF(function_name_, "a thread (tid %d) is making JNI calls without being attached", GetTid()); 764a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return; 765a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 766a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 767a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes // Get the *correct* JNIEnv by going through our TLS pointer. 768a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes JNIEnvExt* threadEnv = self->GetJniEnv(); 769a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 7703f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes // Verify that the current thread is (a) attached and (b) associated with 7713f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes // this particular instance of JNIEnv. 77200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers if (soa_.Env() != threadEnv) { 773987560fee798e48fb725c44b796d8ca7a5872ad6Ian Rogers JniAbortF(function_name_, "thread %s using JNIEnv* from thread %s", 774987560fee798e48fb725c44b796d8ca7a5872ad6Ian Rogers ToStr<Thread>(*self).c_str(), ToStr<Thread>(*soa_.Self()).c_str()); 775987560fee798e48fb725c44b796d8ca7a5872ad6Ian Rogers return; 776a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 777a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 7783f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes // Verify that, if this thread previously made a critical "get" call, we 7793f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes // do the corresponding "release" call before we try anything else. 780a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes switch (flags & kFlag_CritMask) { 781a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes case kFlag_CritOkay: // okay to call this method 782a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes break; 783a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes case kFlag_CritBad: // not okay to call 784a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes if (threadEnv->critical) { 7853f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes JniAbortF(function_name_, "thread %s using JNI after critical get", ToStr<Thread>(*self).c_str()); 786a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return; 787a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 788a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes break; 789a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes case kFlag_CritGet: // this is a "get" call 7903f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes // Don't check here; we allow nested gets. 791a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes threadEnv->critical++; 792a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes break; 7937934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom case kFlag_CritRelease: // this is a "release" call 794a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes threadEnv->critical--; 795a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes if (threadEnv->critical < 0) { 7963f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes JniAbortF(function_name_, "thread %s called too many critical releases", ToStr<Thread>(*self).c_str()); 797a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return; 798a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 799a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes break; 800a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes default: 8013d30d9b09c16542d41554aad9f46ec9109ba5cb5Elliott Hughes LOG(FATAL) << "Bad flags (internal error): " << flags; 802a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 803a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 8043f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes // Verify that, if an exception has been raised, the native code doesn't 8053f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes // make any JNI calls other than the Exception* methods. 806a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes if ((flags & kFlag_ExcepOkay) == 0 && self->IsExceptionPending()) { 80762d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers ThrowLocation throw_location; 80862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers mirror::Throwable* exception = self->GetException(&throw_location); 80962d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers std::string type(PrettyTypeOf(exception)); 8108e4d3ed463df1a9f5fdc1e927a6afe6d208558e1Elliott Hughes JniAbortF(function_name_, "JNI %s called with pending exception '%s' thrown in %s", 8118e4d3ed463df1a9f5fdc1e927a6afe6d208558e1Elliott Hughes function_name_, type.c_str(), throw_location.Dump().c_str()); 812a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return; 813a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 814a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 815a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 8163f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes // Verifies that "bytes" points to valid Modified UTF-8 data. 81732ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes void CheckUtfString(const char* bytes, bool nullable) { 818ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (bytes == nullptr) { 819a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes if (!nullable) { 8203f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes JniAbortF(function_name_, "non-nullable const char* was NULL"); 821a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return; 822a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 823a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return; 824a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 825a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 826ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers const char* errorKind = nullptr; 82732ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes uint8_t utf8 = CheckUtfBytes(bytes, &errorKind); 828ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (errorKind != nullptr) { 8293f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes JniAbortF(function_name_, 8303f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes "input is not valid Modified UTF-8: illegal %s byte %#x\n" 8313f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes " string: '%s'", errorKind, utf8, bytes); 832a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return; 833a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 834a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 835a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 83632ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes static uint8_t CheckUtfBytes(const char* bytes, const char** errorKind) { 837a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes while (*bytes != '\0') { 838a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes uint8_t utf8 = *(bytes++); 839a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes // Switch on the high four bits. 840a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes switch (utf8 >> 4) { 841a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes case 0x00: 842a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes case 0x01: 843a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes case 0x02: 844a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes case 0x03: 845a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes case 0x04: 846a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes case 0x05: 847a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes case 0x06: 848a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes case 0x07: 849a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes // Bit pattern 0xxx. No need for any extra bytes. 850a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes break; 851a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes case 0x08: 852a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes case 0x09: 853a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes case 0x0a: 854a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes case 0x0b: 855a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes case 0x0f: 856a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes /* 857a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * Bit pattern 10xx or 1111, which are illegal start bytes. 858a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * Note: 1111 is valid for normal UTF-8, but not the 85978090d119d5e23ff35ecddac1f4a98e4c050bb07Elliott Hughes * Modified UTF-8 used here. 860a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes */ 861a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes *errorKind = "start"; 862a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return utf8; 863a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes case 0x0e: 864a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes // Bit pattern 1110, so there are two additional bytes. 865a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes utf8 = *(bytes++); 866a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes if ((utf8 & 0xc0) != 0x80) { 867a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes *errorKind = "continuation"; 868a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return utf8; 869a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 870a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes // Fall through to take care of the final byte. 871a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes case 0x0c: 872a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes case 0x0d: 873a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes // Bit pattern 110x, so there is one additional byte. 874a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes utf8 = *(bytes++); 875a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes if ((utf8 & 0xc0) != 0x80) { 876a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes *errorKind = "continuation"; 877a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return utf8; 878a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 879a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes break; 880a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 881a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 882a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return 0; 883a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 884a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 88500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers const ScopedObjectAccess soa_; 88632ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes const char* function_name_; 88732ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes int flags_; 88832ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes bool has_method_; 88992cb498ffd2185fc8f8da7cd25fe485d0e7e3355Elliott Hughes int indent_; 890a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 891a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes DISALLOW_COPY_AND_ASSIGN(ScopedCheck); 892a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes}; 893a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 894a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#define CHECK_JNI_ENTRY(flags, types, args...) \ 895a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes ScopedCheck sc(env, flags, __FUNCTION__); \ 89632ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes sc.Check(true, types, ##args) 897a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 898a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#define CHECK_JNI_EXIT(type, exp) ({ \ 8999b3c3cdb62f7142384e6bf2c0cb6e3a76b16f0e3Mathieu Chartier auto _rc = (exp); \ 90032ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes sc.Check(false, type, _rc); \ 901a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes _rc; }) 902a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#define CHECK_JNI_EXIT_VOID() \ 90332ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes sc.Check(false, "V") 904a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 905a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes/* 906a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * =========================================================================== 907a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * Guarded arrays 908a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * =========================================================================== 909a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes */ 910a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 911a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#define kGuardLen 512 /* must be multiple of 2 */ 912a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#define kGuardPattern 0xd5e3 /* uncommon values; d5e3d5e3 invalid addr */ 913a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#define kGuardMagic 0xffd5aa96 914a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 915a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes/* this gets tucked in at the start of the buffer; struct size must be even */ 916a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughesstruct GuardedCopy { 917a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes uint32_t magic; 918a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes uLong adler; 91932ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes size_t original_length; 92032ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes const void* original_ptr; 921a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 922a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes /* find the GuardedCopy given the pointer into the "live" data */ 92332ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes static inline const GuardedCopy* FromData(const void* dataBuf) { 92432ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes return reinterpret_cast<const GuardedCopy*>(ActualBuffer(dataBuf)); 925a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 926a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 927a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes /* 928a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * Create an over-sized buffer to hold the contents of "buf". Copy it in, 929a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * filling in the area around it with guard data. 930a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * 931a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * We use a 16-bit pattern to make a rogue memset less likely to elude us. 932a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes */ 93332ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes static void* Create(const void* buf, size_t len, bool modOkay) { 93432ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes size_t newLen = ActualLength(len); 93532ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes uint8_t* newBuf = DebugAlloc(newLen); 936a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 9373f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes // Fill it in with a pattern. 938ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes uint16_t* pat = reinterpret_cast<uint16_t*>(newBuf); 939a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes for (size_t i = 0; i < newLen / 2; i++) { 940a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes *pat++ = kGuardPattern; 941a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 942a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 9433f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes // Copy the data in; note "len" could be zero. 944a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes memcpy(newBuf + kGuardLen / 2, buf, len); 945a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 9463f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes // If modification is not expected, grab a checksum. 947a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes uLong adler = 0; 948a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes if (!modOkay) { 949a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes adler = adler32(0L, Z_NULL, 0); 950ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes adler = adler32(adler, reinterpret_cast<const Bytef*>(buf), len); 951ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes *reinterpret_cast<uLong*>(newBuf) = adler; 952a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 953a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 954a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes GuardedCopy* pExtra = reinterpret_cast<GuardedCopy*>(newBuf); 955a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes pExtra->magic = kGuardMagic; 956a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes pExtra->adler = adler; 95732ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes pExtra->original_ptr = buf; 95832ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes pExtra->original_length = len; 959a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 960a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return newBuf + kGuardLen / 2; 961a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 962a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 963a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes /* 964a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * Free up the guard buffer, scrub it, and return the original pointer. 965a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes */ 96632ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes static void* Destroy(void* dataBuf) { 96732ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes const GuardedCopy* pExtra = GuardedCopy::FromData(dataBuf); 968ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes void* original_ptr = const_cast<void*>(pExtra->original_ptr); 96932ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes size_t len = pExtra->original_length; 97032ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes DebugFree(dataBuf, len); 97132ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes return original_ptr; 972a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 973a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 974a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes /* 975a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * Verify the guard area and, if "modOkay" is false, that the data itself 976a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * has not been altered. 977a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * 978a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * The caller has already checked that "dataBuf" is non-NULL. 979a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes */ 98032ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes static void Check(const char* functionName, const void* dataBuf, bool modOkay) { 981a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static const uint32_t kMagicCmp = kGuardMagic; 98232ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes const uint8_t* fullBuf = ActualBuffer(dataBuf); 98332ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes const GuardedCopy* pExtra = GuardedCopy::FromData(dataBuf); 984a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 9853f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes // Before we do anything with "pExtra", check the magic number. We 9863f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes // do the check with memcmp rather than "==" in case the pointer is 9873f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes // unaligned. If it points to completely bogus memory we're going 9883f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes // to crash, but there's no easy way around that. 989a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes if (memcmp(&pExtra->magic, &kMagicCmp, 4) != 0) { 990a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes uint8_t buf[4]; 991a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes memcpy(buf, &pExtra->magic, 4); 9923f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes JniAbortF(functionName, 9933f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes "guard magic does not match (found 0x%02x%02x%02x%02x) -- incorrect data pointer %p?", 9947934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom buf[3], buf[2], buf[1], buf[0], dataBuf); // Assumes little-endian. 995a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 996a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 99732ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes size_t len = pExtra->original_length; 998a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 9993f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes // Check bottom half of guard; skip over optional checksum storage. 1000ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes const uint16_t* pat = reinterpret_cast<const uint16_t*>(fullBuf); 1001a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes for (size_t i = sizeof(GuardedCopy) / 2; i < (kGuardLen / 2 - sizeof(GuardedCopy)) / 2; i++) { 1002a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes if (pat[i] != kGuardPattern) { 1003ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers JniAbortF(functionName, "guard pattern(1) disturbed at %p +%zd", fullBuf, i*2); 1004a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1005a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1006a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1007a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes int offset = kGuardLen / 2 + len; 1008a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes if (offset & 0x01) { 10093f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes // Odd byte; expected value depends on endian. 1010a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes const uint16_t patSample = kGuardPattern; 10113f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes uint8_t expected_byte = reinterpret_cast<const uint8_t*>(&patSample)[1]; 10123f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes if (fullBuf[offset] != expected_byte) { 10133f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes JniAbortF(functionName, "guard pattern disturbed in odd byte after %p +%d 0x%02x 0x%02x", 10143f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes fullBuf, offset, fullBuf[offset], expected_byte); 1015a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1016a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes offset++; 1017a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1018a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 10193f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes // Check top half of guard. 1020ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes pat = reinterpret_cast<const uint16_t*>(fullBuf + offset); 1021a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes for (size_t i = 0; i < kGuardLen / 4; i++) { 1022a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes if (pat[i] != kGuardPattern) { 1023ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers JniAbortF(functionName, "guard pattern(2) disturbed at %p +%zd", fullBuf, offset + i*2); 1024a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1025a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1026a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 10273f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes // If modification is not expected, verify checksum. Strictly speaking 10283f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes // this is wrong: if we told the client that we made a copy, there's no 10293f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes // reason they can't alter the buffer. 1030a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes if (!modOkay) { 1031a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes uLong adler = adler32(0L, Z_NULL, 0); 1032a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes adler = adler32(adler, (const Bytef*)dataBuf, len); 1033a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes if (pExtra->adler != adler) { 10343f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes JniAbortF(functionName, "buffer modified (0x%08lx vs 0x%08lx) at address %p", 10353f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes pExtra->adler, adler, dataBuf); 1036a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1037a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1038a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1039a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1040a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes private: 104132ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes static uint8_t* DebugAlloc(size_t len) { 1042ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers void* result = mmap(nullptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0); 1043a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes if (result == MAP_FAILED) { 1044a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes PLOG(FATAL) << "GuardedCopy::create mmap(" << len << ") failed"; 1045a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1046a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return reinterpret_cast<uint8_t*>(result); 1047a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1048a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 104932ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes static void DebugFree(void* dataBuf, size_t len) { 105032ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes uint8_t* fullBuf = ActualBuffer(dataBuf); 105132ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes size_t totalByteCount = ActualLength(len); 1052a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes // TODO: we could mprotect instead, and keep the allocation around for a while. 1053a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes // This would be even more expensive, but it might catch more errors. 1054a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes // if (mprotect(fullBuf, totalByteCount, PROT_NONE) != 0) { 10557b9d996e4cd7d154bb1a244d67139aff0c363cf2Elliott Hughes // PLOG(WARNING) << "mprotect(PROT_NONE) failed"; 1056a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes // } 1057a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes if (munmap(fullBuf, totalByteCount) != 0) { 1058ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes PLOG(FATAL) << "munmap(" << reinterpret_cast<void*>(fullBuf) << ", " << totalByteCount << ") failed"; 1059a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1060a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1061a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 106232ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes static const uint8_t* ActualBuffer(const void* dataBuf) { 1063a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return reinterpret_cast<const uint8_t*>(dataBuf) - kGuardLen / 2; 1064a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1065a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 106632ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes static uint8_t* ActualBuffer(void* dataBuf) { 1067a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return reinterpret_cast<uint8_t*>(dataBuf) - kGuardLen / 2; 1068a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1069a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1070a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes // Underlying length of a user allocation of 'length' bytes. 107132ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes static size_t ActualLength(size_t length) { 1072a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return (length + kGuardLen + 1) & ~0x01; 1073a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1074a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes}; 1075a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1076a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes/* 1077a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * Create a guarded copy of a primitive array. Modifications to the copied 1078a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * data are allowed. Returns a pointer to the copied data. 1079a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes */ 10803f6635a2c84d645002f651c312d53f8348646c1fElliott Hughesstatic void* CreateGuardedPACopy(JNIEnv* env, const jarray java_array, jboolean* isCopy) { 108100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccess soa(env); 1082a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 10832dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Array* a = soa.Decode<mirror::Array*>(java_array); 1084a15e67d5ee5aa9615596cee2be42c2b2caf128c6Ian Rogers size_t component_size = a->GetClass()->GetComponentSize(); 1085a15e67d5ee5aa9615596cee2be42c2b2caf128c6Ian Rogers size_t byte_count = a->GetLength() * component_size; 1086ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers void* result = GuardedCopy::Create(a->GetRawData(component_size, 0), byte_count, true); 1087ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (isCopy != nullptr) { 1088a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes *isCopy = JNI_TRUE; 1089a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1090a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return result; 1091a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes} 1092a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1093a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes/* 1094a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * Perform the array "release" operation, which may or may not copy data 109581ff3184e7eb8de4605c7646674ea4f9fa29b5f3Elliott Hughes * back into the managed heap, and may or may not release the underlying storage. 1096a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes */ 10973f6635a2c84d645002f651c312d53f8348646c1fElliott Hughesstatic void ReleaseGuardedPACopy(JNIEnv* env, jarray java_array, void* dataBuf, int mode) { 109800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccess soa(env); 10992dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Array* a = soa.Decode<mirror::Array*>(java_array); 1100a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 110132ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes GuardedCopy::Check(__FUNCTION__, dataBuf, true); 1102a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1103a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes if (mode != JNI_ABORT) { 110432ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes size_t len = GuardedCopy::FromData(dataBuf)->original_length; 1105ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers memcpy(a->GetRawData(a->GetClass()->GetComponentSize(), 0), dataBuf, len); 1106a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1107a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes if (mode != JNI_COMMIT) { 110832ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes GuardedCopy::Destroy(dataBuf); 1109a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1110a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes} 1111a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1112a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes/* 1113a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * =========================================================================== 1114a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * JNI functions 1115a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes * =========================================================================== 1116a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes */ 1117a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1118a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughesclass CheckJNI { 1119a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes public: 1120a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jint GetVersion(JNIEnv* env) { 1121a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_Default, "E", env); 1122a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return CHECK_JNI_EXIT("I", baseEnv(env)->GetVersion(env)); 1123a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1124a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1125a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jclass DefineClass(JNIEnv* env, const char* name, jobject loader, const jbyte* buf, jsize bufLen) { 1126a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_Default, "EuLpz", env, name, loader, buf, bufLen); 112732ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes sc.CheckClassName(name); 1128a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return CHECK_JNI_EXIT("c", baseEnv(env)->DefineClass(env, name, loader, buf, bufLen)); 1129a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1130a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1131a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jclass FindClass(JNIEnv* env, const char* name) { 1132a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_Default, "Eu", env, name); 113332ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes sc.CheckClassName(name); 1134a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return CHECK_JNI_EXIT("c", baseEnv(env)->FindClass(env, name)); 1135a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1136a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1137e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes static jclass GetSuperclass(JNIEnv* env, jclass c) { 1138e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes CHECK_JNI_ENTRY(kFlag_Default, "Ec", env, c); 1139e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes return CHECK_JNI_EXIT("c", baseEnv(env)->GetSuperclass(env, c)); 1140a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1141a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1142e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes static jboolean IsAssignableFrom(JNIEnv* env, jclass c1, jclass c2) { 1143e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes CHECK_JNI_ENTRY(kFlag_Default, "Ecc", env, c1, c2); 1144e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes return CHECK_JNI_EXIT("b", baseEnv(env)->IsAssignableFrom(env, c1, c2)); 1145a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1146a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1147a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jmethodID FromReflectedMethod(JNIEnv* env, jobject method) { 1148a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_Default, "EL", env, method); 1149a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes // TODO: check that 'field' is a java.lang.reflect.Method. 1150a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return CHECK_JNI_EXIT("m", baseEnv(env)->FromReflectedMethod(env, method)); 1151a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1152a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1153a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jfieldID FromReflectedField(JNIEnv* env, jobject field) { 1154a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_Default, "EL", env, field); 1155a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes // TODO: check that 'field' is a java.lang.reflect.Field. 1156a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return CHECK_JNI_EXIT("f", baseEnv(env)->FromReflectedField(env, field)); 1157a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1158a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1159a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jobject ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID mid, jboolean isStatic) { 1160a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_Default, "Ecmb", env, cls, mid, isStatic); 1161a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return CHECK_JNI_EXIT("L", baseEnv(env)->ToReflectedMethod(env, cls, mid, isStatic)); 1162a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1163a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1164a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jobject ToReflectedField(JNIEnv* env, jclass cls, jfieldID fid, jboolean isStatic) { 1165a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_Default, "Ecfb", env, cls, fid, isStatic); 1166a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return CHECK_JNI_EXIT("L", baseEnv(env)->ToReflectedField(env, cls, fid, isStatic)); 1167a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1168a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1169a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jint Throw(JNIEnv* env, jthrowable obj) { 1170a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_Default, "EL", env, obj); 1171a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes // TODO: check that 'obj' is a java.lang.Throwable. 1172a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return CHECK_JNI_EXIT("I", baseEnv(env)->Throw(env, obj)); 1173a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1174a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1175e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes static jint ThrowNew(JNIEnv* env, jclass c, const char* message) { 1176e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes CHECK_JNI_ENTRY(kFlag_NullableUtf, "Ecu", env, c, message); 1177e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes return CHECK_JNI_EXIT("I", baseEnv(env)->ThrowNew(env, c, message)); 1178a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1179a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1180a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jthrowable ExceptionOccurred(JNIEnv* env) { 1181a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_ExcepOkay, "E", env); 1182a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return CHECK_JNI_EXIT("L", baseEnv(env)->ExceptionOccurred(env)); 1183a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1184a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1185a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static void ExceptionDescribe(JNIEnv* env) { 1186a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_ExcepOkay, "E", env); 1187a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes baseEnv(env)->ExceptionDescribe(env); 1188a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_EXIT_VOID(); 1189a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1190a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1191a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static void ExceptionClear(JNIEnv* env) { 1192a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_ExcepOkay, "E", env); 1193a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes baseEnv(env)->ExceptionClear(env); 1194a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_EXIT_VOID(); 1195a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1196a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1197a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static void FatalError(JNIEnv* env, const char* msg) { 1198c4378df76edd637273813fef4da7f01c4e637defElliott Hughes // The JNI specification doesn't say it's okay to call FatalError with a pending exception, 1199c4378df76edd637273813fef4da7f01c4e637defElliott Hughes // but you're about to abort anyway, and it's quite likely that you have a pending exception, 1200c4378df76edd637273813fef4da7f01c4e637defElliott Hughes // and it's not unimaginable that you don't know that you do. So we allow it. 1201c4378df76edd637273813fef4da7f01c4e637defElliott Hughes CHECK_JNI_ENTRY(kFlag_ExcepOkay | kFlag_NullableUtf, "Eu", env, msg); 1202a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes baseEnv(env)->FatalError(env, msg); 1203a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_EXIT_VOID(); 1204a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1205a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1206a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jint PushLocalFrame(JNIEnv* env, jint capacity) { 1207a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "EI", env, capacity); 1208a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return CHECK_JNI_EXIT("I", baseEnv(env)->PushLocalFrame(env, capacity)); 1209a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1210a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1211a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jobject PopLocalFrame(JNIEnv* env, jobject res) { 1212a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "EL", env, res); 1213a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return CHECK_JNI_EXIT("L", baseEnv(env)->PopLocalFrame(env, res)); 1214a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1215a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1216a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jobject NewGlobalRef(JNIEnv* env, jobject obj) { 1217a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_Default, "EL", env, obj); 1218a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return CHECK_JNI_EXIT("L", baseEnv(env)->NewGlobalRef(env, obj)); 1219a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1220a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1221a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jobject NewLocalRef(JNIEnv* env, jobject ref) { 1222a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_Default, "EL", env, ref); 1223a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return CHECK_JNI_EXIT("L", baseEnv(env)->NewLocalRef(env, ref)); 1224a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1225a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1226a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static void DeleteGlobalRef(JNIEnv* env, jobject globalRef) { 1227a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "EL", env, globalRef); 1228ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (globalRef != nullptr && GetIndirectRefKind(globalRef) != kGlobal) { 12293f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes JniAbortF(__FUNCTION__, "DeleteGlobalRef on %s: %p", 12303f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes ToStr<IndirectRefKind>(GetIndirectRefKind(globalRef)).c_str(), globalRef); 1231a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } else { 1232a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes baseEnv(env)->DeleteGlobalRef(env, globalRef); 1233a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_EXIT_VOID(); 1234a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1235a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1236a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1237a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static void DeleteWeakGlobalRef(JNIEnv* env, jweak weakGlobalRef) { 1238a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "EL", env, weakGlobalRef); 1239ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (weakGlobalRef != nullptr && GetIndirectRefKind(weakGlobalRef) != kWeakGlobal) { 12403f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes JniAbortF(__FUNCTION__, "DeleteWeakGlobalRef on %s: %p", 12413f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes ToStr<IndirectRefKind>(GetIndirectRefKind(weakGlobalRef)).c_str(), weakGlobalRef); 1242a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } else { 1243a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes baseEnv(env)->DeleteWeakGlobalRef(env, weakGlobalRef); 1244a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_EXIT_VOID(); 1245a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1246a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1247a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1248a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static void DeleteLocalRef(JNIEnv* env, jobject localRef) { 1249a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "EL", env, localRef); 1250eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier if (localRef != nullptr && GetIndirectRefKind(localRef) != kLocal && !IsHandleScopeLocalRef(env, localRef)) { 12513f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes JniAbortF(__FUNCTION__, "DeleteLocalRef on %s: %p", 12523f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes ToStr<IndirectRefKind>(GetIndirectRefKind(localRef)).c_str(), localRef); 1253a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } else { 1254a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes baseEnv(env)->DeleteLocalRef(env, localRef); 1255a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_EXIT_VOID(); 1256a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1257a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1258a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1259a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jint EnsureLocalCapacity(JNIEnv *env, jint capacity) { 1260a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_Default, "EI", env, capacity); 1261a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return CHECK_JNI_EXIT("I", baseEnv(env)->EnsureLocalCapacity(env, capacity)); 1262a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1263a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1264a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jboolean IsSameObject(JNIEnv* env, jobject ref1, jobject ref2) { 1265a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_Default, "ELL", env, ref1, ref2); 1266a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return CHECK_JNI_EXIT("b", baseEnv(env)->IsSameObject(env, ref1, ref2)); 1267a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1268a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1269e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes static jobject AllocObject(JNIEnv* env, jclass c) { 1270e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes CHECK_JNI_ENTRY(kFlag_Default, "Ec", env, c); 1271e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes return CHECK_JNI_EXIT("L", baseEnv(env)->AllocObject(env, c)); 1272a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1273a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1274e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes static jobject NewObject(JNIEnv* env, jclass c, jmethodID mid, ...) { 1275e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes CHECK_JNI_ENTRY(kFlag_Default, "Ecm.", env, c, mid); 1276a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes va_list args; 1277a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes va_start(args, mid); 1278e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes jobject result = baseEnv(env)->NewObjectV(env, c, mid, args); 1279a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes va_end(args); 1280a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return CHECK_JNI_EXIT("L", result); 1281a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1282a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1283e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes static jobject NewObjectV(JNIEnv* env, jclass c, jmethodID mid, va_list args) { 1284e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes CHECK_JNI_ENTRY(kFlag_Default, "Ecm.", env, c, mid); 1285e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes return CHECK_JNI_EXIT("L", baseEnv(env)->NewObjectV(env, c, mid, args)); 1286a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1287a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1288e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes static jobject NewObjectA(JNIEnv* env, jclass c, jmethodID mid, jvalue* args) { 1289e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes CHECK_JNI_ENTRY(kFlag_Default, "Ecm.", env, c, mid); 1290e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes return CHECK_JNI_EXIT("L", baseEnv(env)->NewObjectA(env, c, mid, args)); 1291a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1292a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1293a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jclass GetObjectClass(JNIEnv* env, jobject obj) { 1294a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_Default, "EL", env, obj); 1295a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return CHECK_JNI_EXIT("c", baseEnv(env)->GetObjectClass(env, obj)); 1296a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1297a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1298e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes static jboolean IsInstanceOf(JNIEnv* env, jobject obj, jclass c) { 1299e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes CHECK_JNI_ENTRY(kFlag_Default, "ELc", env, obj, c); 1300e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes return CHECK_JNI_EXIT("b", baseEnv(env)->IsInstanceOf(env, obj, c)); 1301a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1302a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1303e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes static jmethodID GetMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) { 1304e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes CHECK_JNI_ENTRY(kFlag_Default, "Ecuu", env, c, name, sig); 1305e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes return CHECK_JNI_EXIT("m", baseEnv(env)->GetMethodID(env, c, name, sig)); 1306a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1307a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1308e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes static jfieldID GetFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) { 1309e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes CHECK_JNI_ENTRY(kFlag_Default, "Ecuu", env, c, name, sig); 1310e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes return CHECK_JNI_EXIT("f", baseEnv(env)->GetFieldID(env, c, name, sig)); 1311a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1312a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1313e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes static jmethodID GetStaticMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) { 1314e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes CHECK_JNI_ENTRY(kFlag_Default, "Ecuu", env, c, name, sig); 1315e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes return CHECK_JNI_EXIT("m", baseEnv(env)->GetStaticMethodID(env, c, name, sig)); 1316a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1317a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1318e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes static jfieldID GetStaticFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) { 1319e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes CHECK_JNI_ENTRY(kFlag_Default, "Ecuu", env, c, name, sig); 1320e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes return CHECK_JNI_EXIT("f", baseEnv(env)->GetStaticFieldID(env, c, name, sig)); 1321a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1322a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1323ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers#define FIELD_ACCESSORS(_ctype, _jname, _jvalue_type, _type) \ 1324e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes static _ctype GetStatic##_jname##Field(JNIEnv* env, jclass c, jfieldID fid) { \ 1325e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes CHECK_JNI_ENTRY(kFlag_Default, "Ecf", env, c, fid); \ 1326e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes sc.CheckStaticFieldID(c, fid); \ 1327e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes return CHECK_JNI_EXIT(_type, baseEnv(env)->GetStatic##_jname##Field(env, c, fid)); \ 1328a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } \ 1329a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static _ctype Get##_jname##Field(JNIEnv* env, jobject obj, jfieldID fid) { \ 1330a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_Default, "ELf", env, obj, fid); \ 133132ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes sc.CheckInstanceFieldID(obj, fid); \ 1332a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return CHECK_JNI_EXIT(_type, baseEnv(env)->Get##_jname##Field(env, obj, fid)); \ 1333a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } \ 1334e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes static void SetStatic##_jname##Field(JNIEnv* env, jclass c, jfieldID fid, _ctype value) { \ 1335e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes CHECK_JNI_ENTRY(kFlag_Default, "Ecf" _type, env, c, fid, value); \ 1336e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes sc.CheckStaticFieldID(c, fid); \ 1337a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes /* "value" arg only used when type == ref */ \ 1338ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers jvalue java_type_value; \ 1339ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers java_type_value._jvalue_type = value; \ 1340ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers sc.CheckFieldType(java_type_value, fid, _type[0], true); \ 1341e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes baseEnv(env)->SetStatic##_jname##Field(env, c, fid, value); \ 1342a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_EXIT_VOID(); \ 1343a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } \ 1344a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static void Set##_jname##Field(JNIEnv* env, jobject obj, jfieldID fid, _ctype value) { \ 1345a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_Default, "ELf" _type, env, obj, fid, value); \ 134632ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes sc.CheckInstanceFieldID(obj, fid); \ 1347a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes /* "value" arg only used when type == ref */ \ 1348ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers jvalue java_type_value; \ 1349ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers java_type_value._jvalue_type = value; \ 1350ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers sc.CheckFieldType(java_type_value, fid, _type[0], false); \ 1351a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes baseEnv(env)->Set##_jname##Field(env, obj, fid, value); \ 1352a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_EXIT_VOID(); \ 1353a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1354a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1355ef7d42fca18c16fbaf103822ad16f23246e2905dIan RogersFIELD_ACCESSORS(jobject, Object, l, "L"); 1356ef7d42fca18c16fbaf103822ad16f23246e2905dIan RogersFIELD_ACCESSORS(jboolean, Boolean, z, "Z"); 1357ef7d42fca18c16fbaf103822ad16f23246e2905dIan RogersFIELD_ACCESSORS(jbyte, Byte, b, "B"); 1358ef7d42fca18c16fbaf103822ad16f23246e2905dIan RogersFIELD_ACCESSORS(jchar, Char, c, "C"); 1359ef7d42fca18c16fbaf103822ad16f23246e2905dIan RogersFIELD_ACCESSORS(jshort, Short, s, "S"); 1360ef7d42fca18c16fbaf103822ad16f23246e2905dIan RogersFIELD_ACCESSORS(jint, Int, i, "I"); 1361ef7d42fca18c16fbaf103822ad16f23246e2905dIan RogersFIELD_ACCESSORS(jlong, Long, j, "J"); 1362ef7d42fca18c16fbaf103822ad16f23246e2905dIan RogersFIELD_ACCESSORS(jfloat, Float, f, "F"); 1363ef7d42fca18c16fbaf103822ad16f23246e2905dIan RogersFIELD_ACCESSORS(jdouble, Double, d, "D"); 1364a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1365a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#define CALL(_ctype, _jname, _retdecl, _retasgn, _retok, _retsig) \ 1366a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes /* Virtual... */ \ 1367a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static _ctype Call##_jname##Method(JNIEnv* env, jobject obj, \ 1368a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes jmethodID mid, ...) \ 1369a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes { \ 1370a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_Default, "ELm.", env, obj, mid); /* TODO: args! */ \ 137132ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes sc.CheckSig(mid, _retsig, false); \ 137232ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes sc.CheckVirtualMethod(obj, mid); \ 1373a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes _retdecl; \ 1374a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes va_list args; \ 1375a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes va_start(args, mid); \ 1376ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes _retasgn(baseEnv(env)->Call##_jname##MethodV(env, obj, mid, args)); \ 1377a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes va_end(args); \ 1378a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes _retok; \ 1379a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } \ 1380a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static _ctype Call##_jname##MethodV(JNIEnv* env, jobject obj, \ 1381a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes jmethodID mid, va_list args) \ 1382a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes { \ 1383a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_Default, "ELm.", env, obj, mid); /* TODO: args! */ \ 138432ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes sc.CheckSig(mid, _retsig, false); \ 138532ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes sc.CheckVirtualMethod(obj, mid); \ 1386a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes _retdecl; \ 1387ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes _retasgn(baseEnv(env)->Call##_jname##MethodV(env, obj, mid, args)); \ 1388a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes _retok; \ 1389a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } \ 1390a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static _ctype Call##_jname##MethodA(JNIEnv* env, jobject obj, \ 1391a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes jmethodID mid, jvalue* args) \ 1392a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes { \ 1393a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_Default, "ELm.", env, obj, mid); /* TODO: args! */ \ 139432ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes sc.CheckSig(mid, _retsig, false); \ 139532ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes sc.CheckVirtualMethod(obj, mid); \ 1396a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes _retdecl; \ 1397ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes _retasgn(baseEnv(env)->Call##_jname##MethodA(env, obj, mid, args)); \ 1398a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes _retok; \ 1399a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } \ 1400a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes /* Non-virtual... */ \ 1401a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static _ctype CallNonvirtual##_jname##Method(JNIEnv* env, \ 1402e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes jobject obj, jclass c, jmethodID mid, ...) \ 1403a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes { \ 1404e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes CHECK_JNI_ENTRY(kFlag_Default, "ELcm.", env, obj, c, mid); /* TODO: args! */ \ 140532ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes sc.CheckSig(mid, _retsig, false); \ 140632ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes sc.CheckVirtualMethod(obj, mid); \ 1407a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes _retdecl; \ 1408a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes va_list args; \ 1409a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes va_start(args, mid); \ 1410e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes _retasgn(baseEnv(env)->CallNonvirtual##_jname##MethodV(env, obj, c, mid, args)); \ 1411a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes va_end(args); \ 1412a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes _retok; \ 1413a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } \ 1414a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static _ctype CallNonvirtual##_jname##MethodV(JNIEnv* env, \ 1415e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes jobject obj, jclass c, jmethodID mid, va_list args) \ 1416a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes { \ 1417e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes CHECK_JNI_ENTRY(kFlag_Default, "ELcm.", env, obj, c, mid); /* TODO: args! */ \ 141832ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes sc.CheckSig(mid, _retsig, false); \ 141932ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes sc.CheckVirtualMethod(obj, mid); \ 1420a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes _retdecl; \ 1421e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes _retasgn(baseEnv(env)->CallNonvirtual##_jname##MethodV(env, obj, c, mid, args)); \ 1422a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes _retok; \ 1423a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } \ 1424a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static _ctype CallNonvirtual##_jname##MethodA(JNIEnv* env, \ 1425e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes jobject obj, jclass c, jmethodID mid, jvalue* args) \ 1426a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes { \ 1427e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes CHECK_JNI_ENTRY(kFlag_Default, "ELcm.", env, obj, c, mid); /* TODO: args! */ \ 142832ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes sc.CheckSig(mid, _retsig, false); \ 142932ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes sc.CheckVirtualMethod(obj, mid); \ 1430a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes _retdecl; \ 1431e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes _retasgn(baseEnv(env)->CallNonvirtual##_jname##MethodA(env, obj, c, mid, args)); \ 1432a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes _retok; \ 1433a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } \ 1434a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes /* Static... */ \ 1435e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes static _ctype CallStatic##_jname##Method(JNIEnv* env, jclass c, jmethodID mid, ...) \ 1436a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes { \ 1437e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes CHECK_JNI_ENTRY(kFlag_Default, "Ecm.", env, c, mid); /* TODO: args! */ \ 143832ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes sc.CheckSig(mid, _retsig, true); \ 1439e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes sc.CheckStaticMethod(c, mid); \ 1440a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes _retdecl; \ 1441a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes va_list args; \ 1442a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes va_start(args, mid); \ 1443e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes _retasgn(baseEnv(env)->CallStatic##_jname##MethodV(env, c, mid, args)); \ 1444a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes va_end(args); \ 1445a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes _retok; \ 1446a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } \ 1447e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes static _ctype CallStatic##_jname##MethodV(JNIEnv* env, jclass c, jmethodID mid, va_list args) \ 1448a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes { \ 1449e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes CHECK_JNI_ENTRY(kFlag_Default, "Ecm.", env, c, mid); /* TODO: args! */ \ 145032ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes sc.CheckSig(mid, _retsig, true); \ 1451e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes sc.CheckStaticMethod(c, mid); \ 1452a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes _retdecl; \ 1453e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes _retasgn(baseEnv(env)->CallStatic##_jname##MethodV(env, c, mid, args)); \ 1454a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes _retok; \ 1455a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } \ 1456e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes static _ctype CallStatic##_jname##MethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* args) \ 1457a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes { \ 1458e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes CHECK_JNI_ENTRY(kFlag_Default, "Ecm.", env, c, mid); /* TODO: args! */ \ 145932ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes sc.CheckSig(mid, _retsig, true); \ 1460e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes sc.CheckStaticMethod(c, mid); \ 1461a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes _retdecl; \ 1462e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes _retasgn(baseEnv(env)->CallStatic##_jname##MethodA(env, c, mid, args)); \ 1463a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes _retok; \ 1464a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1465a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1466a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#define NON_VOID_RETURN(_retsig, _ctype) return CHECK_JNI_EXIT(_retsig, (_ctype) result) 1467a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#define VOID_RETURN CHECK_JNI_EXIT_VOID() 1468a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 14692dd0e2cea360bc9206eb88ecc40d259e796c239dIan RogersCALL(jobject, Object, mirror::Object* result, result = reinterpret_cast<mirror::Object*>, NON_VOID_RETURN("L", jobject), "L"); 1470ba8eee10607a524f43b55a6f33c13924fb16d435Elliott HughesCALL(jboolean, Boolean, jboolean result, result =, NON_VOID_RETURN("Z", jboolean), "Z"); 1471ba8eee10607a524f43b55a6f33c13924fb16d435Elliott HughesCALL(jbyte, Byte, jbyte result, result =, NON_VOID_RETURN("B", jbyte), "B"); 1472ba8eee10607a524f43b55a6f33c13924fb16d435Elliott HughesCALL(jchar, Char, jchar result, result =, NON_VOID_RETURN("C", jchar), "C"); 1473ba8eee10607a524f43b55a6f33c13924fb16d435Elliott HughesCALL(jshort, Short, jshort result, result =, NON_VOID_RETURN("S", jshort), "S"); 1474ba8eee10607a524f43b55a6f33c13924fb16d435Elliott HughesCALL(jint, Int, jint result, result =, NON_VOID_RETURN("I", jint), "I"); 1475ba8eee10607a524f43b55a6f33c13924fb16d435Elliott HughesCALL(jlong, Long, jlong result, result =, NON_VOID_RETURN("J", jlong), "J"); 1476ba8eee10607a524f43b55a6f33c13924fb16d435Elliott HughesCALL(jfloat, Float, jfloat result, result =, NON_VOID_RETURN("F", jfloat), "F"); 1477ba8eee10607a524f43b55a6f33c13924fb16d435Elliott HughesCALL(jdouble, Double, jdouble result, result =, NON_VOID_RETURN("D", jdouble), "D"); 1478a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott HughesCALL(void, Void, , , VOID_RETURN, "V"); 1479a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1480a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jstring NewString(JNIEnv* env, const jchar* unicodeChars, jsize len) { 1481a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_Default, "Epz", env, unicodeChars, len); 1482a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return CHECK_JNI_EXIT("s", baseEnv(env)->NewString(env, unicodeChars, len)); 1483a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1484a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1485a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jsize GetStringLength(JNIEnv* env, jstring string) { 1486a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_CritOkay, "Es", env, string); 1487a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return CHECK_JNI_EXIT("I", baseEnv(env)->GetStringLength(env, string)); 1488a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1489a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1490a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static const jchar* GetStringChars(JNIEnv* env, jstring java_string, jboolean* isCopy) { 1491a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_CritOkay, "Esp", env, java_string, isCopy); 1492a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes const jchar* result = baseEnv(env)->GetStringChars(env, java_string, isCopy); 1493ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (sc.ForceCopy() && result != nullptr) { 14942dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::String* s = sc.soa().Decode<mirror::String*>(java_string); 1495a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes int byteCount = s->GetLength() * 2; 149632ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes result = (const jchar*) GuardedCopy::Create(result, byteCount, false); 1497ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (isCopy != nullptr) { 1498a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes *isCopy = JNI_TRUE; 1499a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1500a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1501a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return CHECK_JNI_EXIT("p", result); 1502a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1503a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1504a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static void ReleaseStringChars(JNIEnv* env, jstring string, const jchar* chars) { 1505a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "Esp", env, string, chars); 150632ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes sc.CheckNonNull(chars); 150732ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes if (sc.ForceCopy()) { 150832ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes GuardedCopy::Check(__FUNCTION__, chars, false); 1509ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes chars = reinterpret_cast<const jchar*>(GuardedCopy::Destroy(const_cast<jchar*>(chars))); 1510a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1511a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes baseEnv(env)->ReleaseStringChars(env, string, chars); 1512a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_EXIT_VOID(); 1513a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1514a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1515a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jstring NewStringUTF(JNIEnv* env, const char* bytes) { 15167934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom CHECK_JNI_ENTRY(kFlag_NullableUtf, "Eu", env, bytes); // TODO: show pointer and truncate string. 1517a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return CHECK_JNI_EXIT("s", baseEnv(env)->NewStringUTF(env, bytes)); 1518a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1519a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1520a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jsize GetStringUTFLength(JNIEnv* env, jstring string) { 1521a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_CritOkay, "Es", env, string); 1522a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return CHECK_JNI_EXIT("I", baseEnv(env)->GetStringUTFLength(env, string)); 1523a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1524a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1525a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static const char* GetStringUTFChars(JNIEnv* env, jstring string, jboolean* isCopy) { 1526a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_CritOkay, "Esp", env, string, isCopy); 1527a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes const char* result = baseEnv(env)->GetStringUTFChars(env, string, isCopy); 1528ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (sc.ForceCopy() && result != nullptr) { 152932ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes result = (const char*) GuardedCopy::Create(result, strlen(result) + 1, false); 1530ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (isCopy != nullptr) { 1531a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes *isCopy = JNI_TRUE; 1532a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1533a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 15347934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom return CHECK_JNI_EXIT("u", result); // TODO: show pointer and truncate string. 1535a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1536a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1537a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static void ReleaseStringUTFChars(JNIEnv* env, jstring string, const char* utf) { 15387934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom CHECK_JNI_ENTRY(kFlag_ExcepOkay | kFlag_Release, "Esu", env, string, utf); // TODO: show pointer and truncate string. 153932ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes if (sc.ForceCopy()) { 154032ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes GuardedCopy::Check(__FUNCTION__, utf, false); 1541ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes utf = reinterpret_cast<const char*>(GuardedCopy::Destroy(const_cast<char*>(utf))); 1542a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1543a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes baseEnv(env)->ReleaseStringUTFChars(env, string, utf); 1544a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_EXIT_VOID(); 1545a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1546a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1547a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jsize GetArrayLength(JNIEnv* env, jarray array) { 1548a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_CritOkay, "Ea", env, array); 1549a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return CHECK_JNI_EXIT("I", baseEnv(env)->GetArrayLength(env, array)); 1550a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1551a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1552a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jobjectArray NewObjectArray(JNIEnv* env, jsize length, jclass elementClass, jobject initialElement) { 1553a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_Default, "EzcL", env, length, elementClass, initialElement); 1554a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return CHECK_JNI_EXIT("a", baseEnv(env)->NewObjectArray(env, length, elementClass, initialElement)); 1555a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1556a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1557a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jobject GetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index) { 1558a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_Default, "EaI", env, array, index); 1559a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return CHECK_JNI_EXIT("L", baseEnv(env)->GetObjectArrayElement(env, array, index)); 1560a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1561a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1562a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static void SetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index, jobject value) { 1563a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_Default, "EaIL", env, array, index, value); 1564a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes baseEnv(env)->SetObjectArrayElement(env, array, index, value); 1565a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_EXIT_VOID(); 1566a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1567a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1568a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#define NEW_PRIMITIVE_ARRAY(_artype, _jname) \ 1569a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static _artype New##_jname##Array(JNIEnv* env, jsize length) { \ 1570a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_Default, "Ez", env, length); \ 1571a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return CHECK_JNI_EXIT("a", baseEnv(env)->New##_jname##Array(env, length)); \ 1572a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1573a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott HughesNEW_PRIMITIVE_ARRAY(jbooleanArray, Boolean); 1574a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott HughesNEW_PRIMITIVE_ARRAY(jbyteArray, Byte); 1575a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott HughesNEW_PRIMITIVE_ARRAY(jcharArray, Char); 1576a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott HughesNEW_PRIMITIVE_ARRAY(jshortArray, Short); 1577a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott HughesNEW_PRIMITIVE_ARRAY(jintArray, Int); 1578a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott HughesNEW_PRIMITIVE_ARRAY(jlongArray, Long); 1579a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott HughesNEW_PRIMITIVE_ARRAY(jfloatArray, Float); 1580a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott HughesNEW_PRIMITIVE_ARRAY(jdoubleArray, Double); 1581a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 158232ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughesstruct ForceCopyGetChecker { 1583ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes public: 1584a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes ForceCopyGetChecker(ScopedCheck& sc, jboolean* isCopy) { 158532ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes force_copy = sc.ForceCopy(); 158632ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes no_copy = 0; 1587ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (force_copy && isCopy != nullptr) { 15883f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes // Capture this before the base call tramples on it. 1589ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes no_copy = *reinterpret_cast<uint32_t*>(isCopy); 1590a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1591a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1592a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1593a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes template<typename ResultT> 159432ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes ResultT Check(JNIEnv* env, jarray array, jboolean* isCopy, ResultT result) { 1595ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (force_copy && result != nullptr) { 159677129ff50fc0234b62684e556d2c0bcb86123e80Mathieu Chartier result = reinterpret_cast<ResultT>(CreateGuardedPACopy(env, array, isCopy)); 1597a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1598a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return result; 1599a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1600a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 160132ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes uint32_t no_copy; 160232ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes bool force_copy; 1603a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes}; 1604a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1605a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#define GET_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname) \ 1606a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static _ctype* Get##_jname##ArrayElements(JNIEnv* env, _ctype##Array array, jboolean* isCopy) { \ 1607a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_Default, "Eap", env, array, isCopy); \ 160832ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes _ctype* result = ForceCopyGetChecker(sc, isCopy).Check(env, array, isCopy, baseEnv(env)->Get##_jname##ArrayElements(env, array, isCopy)); \ 1609a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return CHECK_JNI_EXIT("p", result); \ 1610a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1611a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1612a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#define RELEASE_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname) \ 1613a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static void Release##_jname##ArrayElements(JNIEnv* env, _ctype##Array array, _ctype* elems, jint mode) { \ 1614a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "Eapr", env, array, elems, mode); \ 161532ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes sc.CheckNonNull(elems); \ 161632ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes if (sc.ForceCopy()) { \ 1617a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes ReleaseGuardedPACopy(env, array, elems, mode); \ 1618a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } \ 1619a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes baseEnv(env)->Release##_jname##ArrayElements(env, array, elems, mode); \ 1620a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_EXIT_VOID(); \ 1621a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1622a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1623a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#define GET_PRIMITIVE_ARRAY_REGION(_ctype, _jname) \ 1624a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static void Get##_jname##ArrayRegion(JNIEnv* env, _ctype##Array array, jsize start, jsize len, _ctype* buf) { \ 1625a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_Default, "EaIIp", env, array, start, len, buf); \ 1626a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes baseEnv(env)->Get##_jname##ArrayRegion(env, array, start, len, buf); \ 1627a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_EXIT_VOID(); \ 1628a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1629a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1630a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#define SET_PRIMITIVE_ARRAY_REGION(_ctype, _jname) \ 1631a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static void Set##_jname##ArrayRegion(JNIEnv* env, _ctype##Array array, jsize start, jsize len, const _ctype* buf) { \ 1632a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_Default, "EaIIp", env, array, start, len, buf); \ 1633a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes baseEnv(env)->Set##_jname##ArrayRegion(env, array, start, len, buf); \ 1634a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_EXIT_VOID(); \ 1635a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1636a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1637a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes#define PRIMITIVE_ARRAY_FUNCTIONS(_ctype, _jname, _typechar) \ 1638a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes GET_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname); \ 1639a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes RELEASE_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname); \ 1640a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes GET_PRIMITIVE_ARRAY_REGION(_ctype, _jname); \ 1641a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes SET_PRIMITIVE_ARRAY_REGION(_ctype, _jname); 1642a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 16433f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes// TODO: verify primitive array type matches call type. 1644a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott HughesPRIMITIVE_ARRAY_FUNCTIONS(jboolean, Boolean, 'Z'); 1645a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott HughesPRIMITIVE_ARRAY_FUNCTIONS(jbyte, Byte, 'B'); 1646a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott HughesPRIMITIVE_ARRAY_FUNCTIONS(jchar, Char, 'C'); 1647a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott HughesPRIMITIVE_ARRAY_FUNCTIONS(jshort, Short, 'S'); 1648a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott HughesPRIMITIVE_ARRAY_FUNCTIONS(jint, Int, 'I'); 1649a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott HughesPRIMITIVE_ARRAY_FUNCTIONS(jlong, Long, 'J'); 1650a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott HughesPRIMITIVE_ARRAY_FUNCTIONS(jfloat, Float, 'F'); 1651a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott HughesPRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, 'D'); 1652a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1653e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes static jint RegisterNatives(JNIEnv* env, jclass c, const JNINativeMethod* methods, jint nMethods) { 1654e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes CHECK_JNI_ENTRY(kFlag_Default, "EcpI", env, c, methods, nMethods); 1655e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes return CHECK_JNI_EXIT("I", baseEnv(env)->RegisterNatives(env, c, methods, nMethods)); 1656a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1657a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1658e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes static jint UnregisterNatives(JNIEnv* env, jclass c) { 1659e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes CHECK_JNI_ENTRY(kFlag_Default, "Ec", env, c); 1660e84278b035c8a48f6032ef98fae008d875fba7a4Elliott Hughes return CHECK_JNI_EXIT("I", baseEnv(env)->UnregisterNatives(env, c)); 1661a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1662a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1663a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jint MonitorEnter(JNIEnv* env, jobject obj) { 1664a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_Default, "EL", env, obj); 1665a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes if (!sc.CheckInstance(ScopedCheck::kObject, obj)) { 16667934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom return JNI_ERR; // Only for jni_internal_test. Real code will have aborted already. 1667a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes } 1668a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return CHECK_JNI_EXIT("I", baseEnv(env)->MonitorEnter(env, obj)); 1669a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1670a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1671a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jint MonitorExit(JNIEnv* env, jobject obj) { 1672a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "EL", env, obj); 1673a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes if (!sc.CheckInstance(ScopedCheck::kObject, obj)) { 16747934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom return JNI_ERR; // Only for jni_internal_test. Real code will have aborted already. 1675a92853eb60fbce1fa6d3bbd6a6013fb514fdf5cbElliott Hughes } 1676a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return CHECK_JNI_EXIT("I", baseEnv(env)->MonitorExit(env, obj)); 1677a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1678a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1679a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jint GetJavaVM(JNIEnv *env, JavaVM **vm) { 1680a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_Default, "Ep", env, vm); 1681a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return CHECK_JNI_EXIT("I", baseEnv(env)->GetJavaVM(env, vm)); 1682a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1683a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1684a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static void GetStringRegion(JNIEnv* env, jstring str, jsize start, jsize len, jchar* buf) { 1685a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_CritOkay, "EsIIp", env, str, start, len, buf); 1686a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes baseEnv(env)->GetStringRegion(env, str, start, len, buf); 1687a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_EXIT_VOID(); 1688a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1689a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1690a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static void GetStringUTFRegion(JNIEnv* env, jstring str, jsize start, jsize len, char* buf) { 1691a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_CritOkay, "EsIIp", env, str, start, len, buf); 1692a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes baseEnv(env)->GetStringUTFRegion(env, str, start, len, buf); 1693a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_EXIT_VOID(); 1694a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1695a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1696a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static void* GetPrimitiveArrayCritical(JNIEnv* env, jarray array, jboolean* isCopy) { 1697a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_CritGet, "Eap", env, array, isCopy); 1698a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes void* result = baseEnv(env)->GetPrimitiveArrayCritical(env, array, isCopy); 1699ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (sc.ForceCopy() && result != nullptr) { 1700a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes result = CreateGuardedPACopy(env, array, isCopy); 1701a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1702a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return CHECK_JNI_EXIT("p", result); 1703a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1704a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1705a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static void ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array, void* carray, jint mode) { 1706a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_CritRelease | kFlag_ExcepOkay, "Eapr", env, array, carray, mode); 170732ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes sc.CheckNonNull(carray); 170832ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes if (sc.ForceCopy()) { 1709a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes ReleaseGuardedPACopy(env, array, carray, mode); 1710a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1711a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes baseEnv(env)->ReleasePrimitiveArrayCritical(env, array, carray, mode); 1712a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_EXIT_VOID(); 1713a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1714a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1715a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static const jchar* GetStringCritical(JNIEnv* env, jstring java_string, jboolean* isCopy) { 1716a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_CritGet, "Esp", env, java_string, isCopy); 1717a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes const jchar* result = baseEnv(env)->GetStringCritical(env, java_string, isCopy); 1718ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (sc.ForceCopy() && result != nullptr) { 17192dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::String* s = sc.soa().Decode<mirror::String*>(java_string); 1720a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes int byteCount = s->GetLength() * 2; 172132ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes result = (const jchar*) GuardedCopy::Create(result, byteCount, false); 1722ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (isCopy != nullptr) { 1723a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes *isCopy = JNI_TRUE; 1724a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1725a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1726a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return CHECK_JNI_EXIT("p", result); 1727a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1728a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1729a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static void ReleaseStringCritical(JNIEnv* env, jstring string, const jchar* carray) { 1730a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_CritRelease | kFlag_ExcepOkay, "Esp", env, string, carray); 173132ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes sc.CheckNonNull(carray); 173232ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes if (sc.ForceCopy()) { 173332ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes GuardedCopy::Check(__FUNCTION__, carray, false); 1734ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes carray = reinterpret_cast<const jchar*>(GuardedCopy::Destroy(const_cast<jchar*>(carray))); 1735a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1736a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes baseEnv(env)->ReleaseStringCritical(env, string, carray); 1737a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_EXIT_VOID(); 1738a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1739a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1740a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jweak NewWeakGlobalRef(JNIEnv* env, jobject obj) { 1741a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_Default, "EL", env, obj); 1742a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return CHECK_JNI_EXIT("L", baseEnv(env)->NewWeakGlobalRef(env, obj)); 1743a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1744a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1745a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jboolean ExceptionCheck(JNIEnv* env) { 1746a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_CritOkay | kFlag_ExcepOkay, "E", env); 1747a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return CHECK_JNI_EXIT("b", baseEnv(env)->ExceptionCheck(env)); 1748a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1749a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1750a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jobjectRefType GetObjectRefType(JNIEnv* env, jobject obj) { 1751a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes // Note: we use "Ep" rather than "EL" because this is the one JNI function 1752a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes // that it's okay to pass an invalid reference to. 1753a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_Default, "Ep", env, obj); 1754a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes // TODO: proper decoding of jobjectRefType! 1755a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return CHECK_JNI_EXIT("I", baseEnv(env)->GetObjectRefType(env, obj)); 1756a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1757a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1758a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jobject NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity) { 1759a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_Default, "EpJ", env, address, capacity); 1760ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (address == nullptr) { 17613f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes JniAbortF(__FUNCTION__, "non-nullable address is NULL"); 176245d26c86b00580593067ca42091ad66cf7dc4f7cBrian Carlstrom return nullptr; 1763a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1764a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return CHECK_JNI_EXIT("L", baseEnv(env)->NewDirectByteBuffer(env, address, capacity)); 1765a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1766a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1767a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static void* GetDirectBufferAddress(JNIEnv* env, jobject buf) { 1768a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_Default, "EL", env, buf); 1769a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes // TODO: check that 'buf' is a java.nio.Buffer. 1770a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return CHECK_JNI_EXIT("p", baseEnv(env)->GetDirectBufferAddress(env, buf)); 1771a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1772a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1773a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jlong GetDirectBufferCapacity(JNIEnv* env, jobject buf) { 1774a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CHECK_JNI_ENTRY(kFlag_Default, "EL", env, buf); 1775a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes // TODO: check that 'buf' is a java.nio.Buffer. 1776a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return CHECK_JNI_EXIT("J", baseEnv(env)->GetDirectBufferCapacity(env, buf)); 1777a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1778a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1779a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes private: 1780a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static inline const JNINativeInterface* baseEnv(JNIEnv* env) { 1781a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return reinterpret_cast<JNIEnvExt*>(env)->unchecked_functions; 1782a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 1783a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes}; 1784a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 1785a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughesconst JNINativeInterface gCheckNativeInterface = { 1786ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers nullptr, // reserved0. 1787ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers nullptr, // reserved1. 1788ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers nullptr, // reserved2. 1789ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers nullptr, // reserved3. 1790a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetVersion, 1791a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::DefineClass, 1792a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::FindClass, 1793a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::FromReflectedMethod, 1794a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::FromReflectedField, 1795a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::ToReflectedMethod, 1796a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetSuperclass, 1797a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::IsAssignableFrom, 1798a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::ToReflectedField, 1799a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::Throw, 1800a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::ThrowNew, 1801a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::ExceptionOccurred, 1802a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::ExceptionDescribe, 1803a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::ExceptionClear, 1804a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::FatalError, 1805a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::PushLocalFrame, 1806a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::PopLocalFrame, 1807a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::NewGlobalRef, 1808a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::DeleteGlobalRef, 1809a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::DeleteLocalRef, 1810a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::IsSameObject, 1811a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::NewLocalRef, 1812a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::EnsureLocalCapacity, 1813a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::AllocObject, 1814a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::NewObject, 1815a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::NewObjectV, 1816a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::NewObjectA, 1817a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetObjectClass, 1818a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::IsInstanceOf, 1819a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetMethodID, 1820a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallObjectMethod, 1821a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallObjectMethodV, 1822a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallObjectMethodA, 1823a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallBooleanMethod, 1824a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallBooleanMethodV, 1825a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallBooleanMethodA, 1826a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallByteMethod, 1827a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallByteMethodV, 1828a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallByteMethodA, 1829a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallCharMethod, 1830a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallCharMethodV, 1831a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallCharMethodA, 1832a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallShortMethod, 1833a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallShortMethodV, 1834a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallShortMethodA, 1835a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallIntMethod, 1836a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallIntMethodV, 1837a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallIntMethodA, 1838a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallLongMethod, 1839a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallLongMethodV, 1840a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallLongMethodA, 1841a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallFloatMethod, 1842a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallFloatMethodV, 1843a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallFloatMethodA, 1844a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallDoubleMethod, 1845a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallDoubleMethodV, 1846a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallDoubleMethodA, 1847a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallVoidMethod, 1848a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallVoidMethodV, 1849a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallVoidMethodA, 1850a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualObjectMethod, 1851a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualObjectMethodV, 1852a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualObjectMethodA, 1853a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualBooleanMethod, 1854a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualBooleanMethodV, 1855a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualBooleanMethodA, 1856a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualByteMethod, 1857a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualByteMethodV, 1858a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualByteMethodA, 1859a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualCharMethod, 1860a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualCharMethodV, 1861a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualCharMethodA, 1862a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualShortMethod, 1863a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualShortMethodV, 1864a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualShortMethodA, 1865a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualIntMethod, 1866a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualIntMethodV, 1867a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualIntMethodA, 1868a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualLongMethod, 1869a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualLongMethodV, 1870a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualLongMethodA, 1871a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualFloatMethod, 1872a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualFloatMethodV, 1873a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualFloatMethodA, 1874a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualDoubleMethod, 1875a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualDoubleMethodV, 1876a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualDoubleMethodA, 1877a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualVoidMethod, 1878a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualVoidMethodV, 1879a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallNonvirtualVoidMethodA, 1880a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetFieldID, 1881a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetObjectField, 1882a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetBooleanField, 1883a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetByteField, 1884a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetCharField, 1885a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetShortField, 1886a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetIntField, 1887a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetLongField, 1888a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetFloatField, 1889a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetDoubleField, 1890a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::SetObjectField, 1891a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::SetBooleanField, 1892a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::SetByteField, 1893a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::SetCharField, 1894a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::SetShortField, 1895a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::SetIntField, 1896a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::SetLongField, 1897a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::SetFloatField, 1898a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::SetDoubleField, 1899a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetStaticMethodID, 1900a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticObjectMethod, 1901a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticObjectMethodV, 1902a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticObjectMethodA, 1903a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticBooleanMethod, 1904a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticBooleanMethodV, 1905a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticBooleanMethodA, 1906a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticByteMethod, 1907a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticByteMethodV, 1908a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticByteMethodA, 1909a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticCharMethod, 1910a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticCharMethodV, 1911a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticCharMethodA, 1912a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticShortMethod, 1913a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticShortMethodV, 1914a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticShortMethodA, 1915a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticIntMethod, 1916a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticIntMethodV, 1917a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticIntMethodA, 1918a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticLongMethod, 1919a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticLongMethodV, 1920a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticLongMethodA, 1921a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticFloatMethod, 1922a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticFloatMethodV, 1923a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticFloatMethodA, 1924a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticDoubleMethod, 1925a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticDoubleMethodV, 1926a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticDoubleMethodA, 1927a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticVoidMethod, 1928a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticVoidMethodV, 1929a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::CallStaticVoidMethodA, 1930a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetStaticFieldID, 1931a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetStaticObjectField, 1932a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetStaticBooleanField, 1933a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetStaticByteField, 1934a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetStaticCharField, 1935a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetStaticShortField, 1936a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetStaticIntField, 1937a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetStaticLongField, 1938a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetStaticFloatField, 1939a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetStaticDoubleField, 1940a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::SetStaticObjectField, 1941a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::SetStaticBooleanField, 1942a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::SetStaticByteField, 1943a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::SetStaticCharField, 1944a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::SetStaticShortField, 1945a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::SetStaticIntField, 1946a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::SetStaticLongField, 1947a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::SetStaticFloatField, 1948a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::SetStaticDoubleField, 1949a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::NewString, 1950a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetStringLength, 1951a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetStringChars, 1952a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::ReleaseStringChars, 1953a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::NewStringUTF, 1954a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetStringUTFLength, 1955a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetStringUTFChars, 1956a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::ReleaseStringUTFChars, 1957a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetArrayLength, 1958a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::NewObjectArray, 1959a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetObjectArrayElement, 1960a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::SetObjectArrayElement, 1961a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::NewBooleanArray, 1962a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::NewByteArray, 1963a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::NewCharArray, 1964a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::NewShortArray, 1965a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::NewIntArray, 1966a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::NewLongArray, 1967a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::NewFloatArray, 1968a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::NewDoubleArray, 1969a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetBooleanArrayElements, 1970a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetByteArrayElements, 1971a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetCharArrayElements, 1972a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetShortArrayElements, 1973a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetIntArrayElements, 1974a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetLongArrayElements, 1975a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetFloatArrayElements, 1976a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetDoubleArrayElements, 1977a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::ReleaseBooleanArrayElements, 1978a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::ReleaseByteArrayElements, 1979a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::ReleaseCharArrayElements, 1980a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::ReleaseShortArrayElements, 1981a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::ReleaseIntArrayElements, 1982a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::ReleaseLongArrayElements, 1983a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::ReleaseFloatArrayElements, 1984a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::ReleaseDoubleArrayElements, 1985a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetBooleanArrayRegion, 1986a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetByteArrayRegion, 1987a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetCharArrayRegion, 1988a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetShortArrayRegion, 1989a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetIntArrayRegion, 1990a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetLongArrayRegion, 1991a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetFloatArrayRegion, 1992a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetDoubleArrayRegion, 1993a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::SetBooleanArrayRegion, 1994a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::SetByteArrayRegion, 1995a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::SetCharArrayRegion, 1996a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::SetShortArrayRegion, 1997a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::SetIntArrayRegion, 1998a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::SetLongArrayRegion, 1999a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::SetFloatArrayRegion, 2000a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::SetDoubleArrayRegion, 2001a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::RegisterNatives, 2002a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::UnregisterNatives, 2003a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::MonitorEnter, 2004a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::MonitorExit, 2005a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetJavaVM, 2006a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetStringRegion, 2007a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetStringUTFRegion, 2008a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetPrimitiveArrayCritical, 2009a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::ReleasePrimitiveArrayCritical, 2010a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetStringCritical, 2011a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::ReleaseStringCritical, 2012a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::NewWeakGlobalRef, 2013a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::DeleteWeakGlobalRef, 2014a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::ExceptionCheck, 2015a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::NewDirectByteBuffer, 2016a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetDirectBufferAddress, 2017a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetDirectBufferCapacity, 2018a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJNI::GetObjectRefType, 2019a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes}; 2020a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 2021a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughesconst JNINativeInterface* GetCheckJniNativeInterface() { 2022a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return &gCheckNativeInterface; 2023a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes} 2024a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 2025a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughesclass CheckJII { 2026ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes public: 2027a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jint DestroyJavaVM(JavaVM* vm) { 2028a09576416788b916095739e43a16917e7948f3a4Elliott Hughes ScopedCheck sc(vm, false, __FUNCTION__); 202932ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes sc.Check(true, "v", vm); 203032ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes return CHECK_JNI_EXIT("I", BaseVm(vm)->DestroyJavaVM(vm)); 2031a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 2032a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 2033a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jint AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* thr_args) { 2034a09576416788b916095739e43a16917e7948f3a4Elliott Hughes ScopedCheck sc(vm, false, __FUNCTION__); 203532ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes sc.Check(true, "vpp", vm, p_env, thr_args); 203632ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes return CHECK_JNI_EXIT("I", BaseVm(vm)->AttachCurrentThread(vm, p_env, thr_args)); 2037a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 2038a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 2039a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jint AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env, void* thr_args) { 2040a09576416788b916095739e43a16917e7948f3a4Elliott Hughes ScopedCheck sc(vm, false, __FUNCTION__); 204132ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes sc.Check(true, "vpp", vm, p_env, thr_args); 204232ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes return CHECK_JNI_EXIT("I", BaseVm(vm)->AttachCurrentThreadAsDaemon(vm, p_env, thr_args)); 2043a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 2044a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 2045a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jint DetachCurrentThread(JavaVM* vm) { 2046a09576416788b916095739e43a16917e7948f3a4Elliott Hughes ScopedCheck sc(vm, true, __FUNCTION__); 204732ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes sc.Check(true, "v", vm); 204832ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes return CHECK_JNI_EXIT("I", BaseVm(vm)->DetachCurrentThread(vm)); 2049a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 2050a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 2051a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes static jint GetEnv(JavaVM* vm, void** env, jint version) { 2052a09576416788b916095739e43a16917e7948f3a4Elliott Hughes ScopedCheck sc(vm, true, __FUNCTION__); 205383a25328c595975097cf3948451088cbfc64fc09Elliott Hughes sc.Check(true, "vpI", vm); 205432ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes return CHECK_JNI_EXIT("I", BaseVm(vm)->GetEnv(vm, env, version)); 2055a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 2056a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 2057a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes private: 205832ae6e33303cc51b524d9eef9b2dd547ecc638e9Elliott Hughes static inline const JNIInvokeInterface* BaseVm(JavaVM* vm) { 2059a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return reinterpret_cast<JavaVMExt*>(vm)->unchecked_functions; 2060a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes } 2061a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes}; 2062a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 2063a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughesconst JNIInvokeInterface gCheckInvokeInterface = { 2064ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers nullptr, // reserved0 2065ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers nullptr, // reserved1 2066ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers nullptr, // reserved2 2067a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJII::DestroyJavaVM, 2068a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJII::AttachCurrentThread, 2069a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJII::DetachCurrentThread, 2070a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJII::GetEnv, 2071a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes CheckJII::AttachCurrentThreadAsDaemon 2072a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes}; 2073a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 2074a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughesconst JNIInvokeInterface* GetCheckJniInvokeInterface() { 2075a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes return &gCheckInvokeInterface; 2076a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes} 2077a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes 2078a2501990dd0f68baf38ce19251949d7bb3ecfe5aElliott Hughes} // namespace art 2079