1 /*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "jni_internal.h"
18
19 #include <sys/mman.h>
20 #include <zlib.h>
21
22 #include "base/logging.h"
23 #include "class_linker.h"
24 #include "class_linker-inl.h"
25 #include "dex_file-inl.h"
26 #include "field_helper.h"
27 #include "gc/space/space.h"
28 #include "mirror/art_field-inl.h"
29 #include "mirror/art_method-inl.h"
30 #include "mirror/class-inl.h"
31 #include "mirror/object-inl.h"
32 #include "mirror/object_array-inl.h"
33 #include "mirror/string-inl.h"
34 #include "mirror/throwable.h"
35 #include "runtime.h"
36 #include "scoped_thread_state_change.h"
37 #include "thread.h"
38
39 namespace art {
40
JniAbort(const char * jni_function_name,const char * msg)41 static void JniAbort(const char* jni_function_name, const char* msg) {
42 Thread* self = Thread::Current();
43 ScopedObjectAccess soa(self);
44 mirror::ArtMethod* current_method = self->GetCurrentMethod(nullptr);
45
46 std::ostringstream os;
47 os << "JNI DETECTED ERROR IN APPLICATION: " << msg;
48
49 if (jni_function_name != nullptr) {
50 os << "\n in call to " << jni_function_name;
51 }
52 // TODO: is this useful given that we're about to dump the calling thread's stack?
53 if (current_method != nullptr) {
54 os << "\n from " << PrettyMethod(current_method);
55 }
56 os << "\n";
57 self->Dump(os);
58
59 JavaVMExt* vm = Runtime::Current()->GetJavaVM();
60 if (vm->check_jni_abort_hook != nullptr) {
61 vm->check_jni_abort_hook(vm->check_jni_abort_hook_data, os.str());
62 } else {
63 // Ensure that we get a native stack trace for this thread.
64 self->TransitionFromRunnableToSuspended(kNative);
65 LOG(FATAL) << os.str();
66 self->TransitionFromSuspendedToRunnable(); // Unreachable, keep annotalysis happy.
67 }
68 }
69
JniAbortV(const char * jni_function_name,const char * fmt,va_list ap)70 static void JniAbortV(const char* jni_function_name, const char* fmt, va_list ap) {
71 std::string msg;
72 StringAppendV(&msg, fmt, ap);
73 JniAbort(jni_function_name, msg.c_str());
74 }
75
JniAbortF(const char * jni_function_name,const char * fmt,...)76 void JniAbortF(const char* jni_function_name, const char* fmt, ...) {
77 va_list args;
78 va_start(args, fmt);
79 JniAbortV(jni_function_name, fmt, args);
80 va_end(args);
81 }
82
83 /*
84 * ===========================================================================
85 * JNI function helpers
86 * ===========================================================================
87 */
88
IsHandleScopeLocalRef(JNIEnv * env,jobject localRef)89 static bool IsHandleScopeLocalRef(JNIEnv* env, jobject localRef) {
90 return GetIndirectRefKind(localRef) == kHandleScopeOrInvalid &&
91 reinterpret_cast<JNIEnvExt*>(env)->self->HandleScopeContains(localRef);
92 }
93
94 // Flags passed into ScopedCheck.
95 #define kFlag_Default 0x0000
96
97 #define kFlag_CritBad 0x0000 // Calling while in critical is not allowed.
98 #define kFlag_CritOkay 0x0001 // Calling while in critical is allowed.
99 #define kFlag_CritGet 0x0002 // This is a critical "get".
100 #define kFlag_CritRelease 0x0003 // This is a critical "release".
101 #define kFlag_CritMask 0x0003 // Bit mask to get "crit" value.
102
103 #define kFlag_ExcepBad 0x0000 // Raised exceptions are not allowed.
104 #define kFlag_ExcepOkay 0x0004 // Raised exceptions are allowed.
105
106 #define kFlag_Release 0x0010 // Are we in a non-critical release function?
107 #define kFlag_NullableUtf 0x0020 // Are our UTF parameters nullable?
108
109 #define kFlag_Invocation 0x8000 // Part of the invocation interface (JavaVM*).
110
111 #define kFlag_ForceTrace 0x80000000 // Add this to a JNI function's flags if you want to trace every call.
112
113 static const char* gBuiltInPrefixes[] = {
114 "Landroid/",
115 "Lcom/android/",
116 "Lcom/google/android/",
117 "Ldalvik/",
118 "Ljava/",
119 "Ljavax/",
120 "Llibcore/",
121 "Lorg/apache/harmony/",
122 nullptr
123 };
124
ShouldTrace(JavaVMExt * vm,mirror::ArtMethod * method)125 static bool ShouldTrace(JavaVMExt* vm, mirror::ArtMethod* method)
126 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
127 // If both "-Xcheck:jni" and "-Xjnitrace:" are enabled, we print trace messages
128 // when a native method that matches the -Xjnitrace argument calls a JNI function
129 // such as NewByteArray.
130 // If -verbose:third-party-jni is on, we want to log any JNI function calls
131 // made by a third-party native method.
132 std::string class_name(method->GetDeclaringClassDescriptor());
133 if (!vm->trace.empty() && class_name.find(vm->trace) != std::string::npos) {
134 return true;
135 }
136 if (VLOG_IS_ON(third_party_jni)) {
137 // Return true if we're trying to log all third-party JNI activity and 'method' doesn't look
138 // like part of Android.
139 for (size_t i = 0; gBuiltInPrefixes[i] != nullptr; ++i) {
140 if (StartsWith(class_name, gBuiltInPrefixes[i])) {
141 return false;
142 }
143 }
144 return true;
145 }
146 return false;
147 }
148
149 class ScopedCheck {
150 public:
151 // For JNIEnv* functions.
ScopedCheck(JNIEnv * env,int flags,const char * functionName)152 explicit ScopedCheck(JNIEnv* env, int flags, const char* functionName)
153 SHARED_LOCK_FUNCTION(Locks::mutator_lock_)
154 : soa_(env) {
155 Init(flags, functionName, true);
156 CheckThread(flags);
157 }
158
159 // For JavaVM* functions.
160 // TODO: it's not correct that this is a lock function, but making it so aids annotalysis.
ScopedCheck(JavaVM * vm,bool has_method,const char * functionName)161 explicit ScopedCheck(JavaVM* vm, bool has_method, const char* functionName)
162 SHARED_LOCK_FUNCTION(Locks::mutator_lock_)
163 : soa_(vm) {
164 Init(kFlag_Invocation, functionName, has_method);
165 }
166
UNLOCK_FUNCTION(Locks::mutator_lock_)167 ~ScopedCheck() UNLOCK_FUNCTION(Locks::mutator_lock_) {}
168
soa()169 const ScopedObjectAccess& soa() {
170 return soa_;
171 }
172
ForceCopy()173 bool ForceCopy() {
174 return Runtime::Current()->GetJavaVM()->force_copy;
175 }
176
177 // Checks that 'class_name' is a valid "fully-qualified" JNI class name, like "java/lang/Thread"
178 // or "[Ljava/lang/Object;". A ClassLoader can actually normalize class names a couple of
179 // times, so using "java.lang.Thread" instead of "java/lang/Thread" might work in some
180 // circumstances, but this is incorrect.
CheckClassName(const char * class_name)181 void CheckClassName(const char* class_name) {
182 if ((class_name == nullptr) || !IsValidJniClassName(class_name)) {
183 JniAbortF(function_name_,
184 "illegal class name '%s'\n"
185 " (should be of the form 'package/Class', [Lpackage/Class;' or '[[B')",
186 class_name);
187 }
188 }
189
190 /*
191 * Verify that the field is of the appropriate type. If the field has an
192 * object type, "java_object" is the object we're trying to assign into it.
193 *
194 * Works for both static and instance fields.
195 */
CheckFieldType(jvalue value,jfieldID fid,char prim,bool isStatic)196 void CheckFieldType(jvalue value, jfieldID fid, char prim, bool isStatic)
197 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
198 StackHandleScope<1> hs(Thread::Current());
199 Handle<mirror::ArtField> f(hs.NewHandle(CheckFieldID(fid)));
200 if (f.Get() == nullptr) {
201 return;
202 }
203 mirror::Class* field_type = FieldHelper(f).GetType();
204 if (!field_type->IsPrimitive()) {
205 jobject java_object = value.l;
206 if (java_object != nullptr) {
207 mirror::Object* obj = soa_.Decode<mirror::Object*>(java_object);
208 // If java_object is a weak global ref whose referent has been cleared,
209 // obj will be NULL. Otherwise, obj should always be non-NULL
210 // and valid.
211 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(obj)) {
212 Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
213 JniAbortF(function_name_, "field operation on invalid %s: %p",
214 ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(), java_object);
215 return;
216 } else {
217 if (!obj->InstanceOf(field_type)) {
218 JniAbortF(function_name_, "attempt to set field %s with value of wrong type: %s",
219 PrettyField(f.Get()).c_str(), PrettyTypeOf(obj).c_str());
220 return;
221 }
222 }
223 }
224 } else if (field_type != Runtime::Current()->GetClassLinker()->FindPrimitiveClass(prim)) {
225 JniAbortF(function_name_, "attempt to set field %s with value of wrong type: %c",
226 PrettyField(f.Get()).c_str(), prim);
227 return;
228 }
229
230 if (isStatic != f.Get()->IsStatic()) {
231 if (isStatic) {
232 JniAbortF(function_name_, "accessing non-static field %s as static",
233 PrettyField(f.Get()).c_str());
234 } else {
235 JniAbortF(function_name_, "accessing static field %s as non-static",
236 PrettyField(f.Get()).c_str());
237 }
238 return;
239 }
240 }
241
242 /*
243 * Verify that this instance field ID is valid for this object.
244 *
245 * Assumes "jobj" has already been validated.
246 */
CheckInstanceFieldID(jobject java_object,jfieldID fid)247 void CheckInstanceFieldID(jobject java_object, jfieldID fid)
248 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
249 mirror::Object* o = soa_.Decode<mirror::Object*>(java_object);
250 if (o == nullptr || !Runtime::Current()->GetHeap()->IsValidObjectAddress(o)) {
251 Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
252 JniAbortF(function_name_, "field operation on invalid %s: %p",
253 ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(), java_object);
254 return;
255 }
256
257 mirror::ArtField* f = CheckFieldID(fid);
258 if (f == nullptr) {
259 return;
260 }
261 mirror::Class* c = o->GetClass();
262 if (c->FindInstanceField(f->GetName(), f->GetTypeDescriptor()) == nullptr) {
263 JniAbortF(function_name_, "jfieldID %s not valid for an object of class %s",
264 PrettyField(f).c_str(), PrettyTypeOf(o).c_str());
265 }
266 }
267
268 /*
269 * Verify that the pointer value is non-NULL.
270 */
CheckNonNull(const void * ptr)271 void CheckNonNull(const void* ptr) {
272 if (ptr == nullptr) {
273 JniAbortF(function_name_, "non-nullable argument was NULL");
274 }
275 }
276
277 /*
278 * Verify that the method's return type matches the type of call.
279 * 'expectedType' will be "L" for all objects, including arrays.
280 */
CheckSig(jmethodID mid,const char * expectedType,bool isStatic)281 void CheckSig(jmethodID mid, const char* expectedType, bool isStatic)
282 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
283 mirror::ArtMethod* m = CheckMethodID(mid);
284 if (m == nullptr) {
285 return;
286 }
287 if (*expectedType != m->GetShorty()[0]) {
288 JniAbortF(function_name_, "the return type of %s does not match %s",
289 function_name_, PrettyMethod(m).c_str());
290 }
291 if (isStatic != m->IsStatic()) {
292 if (isStatic) {
293 JniAbortF(function_name_, "calling non-static method %s with %s",
294 PrettyMethod(m).c_str(), function_name_);
295 } else {
296 JniAbortF(function_name_, "calling static method %s with %s",
297 PrettyMethod(m).c_str(), function_name_);
298 }
299 }
300 }
301
302 /*
303 * Verify that this static field ID is valid for this class.
304 *
305 * Assumes "java_class" has already been validated.
306 */
CheckStaticFieldID(jclass java_class,jfieldID fid)307 void CheckStaticFieldID(jclass java_class, jfieldID fid)
308 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
309 mirror::Class* c = soa_.Decode<mirror::Class*>(java_class);
310 mirror::ArtField* f = CheckFieldID(fid);
311 if (f == nullptr) {
312 return;
313 }
314 if (f->GetDeclaringClass() != c) {
315 JniAbortF(function_name_, "static jfieldID %p not valid for class %s",
316 fid, PrettyClass(c).c_str());
317 }
318 }
319
320 /*
321 * Verify that "mid" is appropriate for "java_class".
322 *
323 * A mismatch isn't dangerous, because the jmethodID defines the class. In
324 * fact, java_class is unused in the implementation. It's best if we don't
325 * allow bad code in the system though.
326 *
327 * Instances of "java_class" must be instances of the method's declaring class.
328 */
CheckStaticMethod(jclass java_class,jmethodID mid)329 void CheckStaticMethod(jclass java_class, jmethodID mid)
330 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
331 mirror::ArtMethod* m = CheckMethodID(mid);
332 if (m == nullptr) {
333 return;
334 }
335 mirror::Class* c = soa_.Decode<mirror::Class*>(java_class);
336 if (!m->GetDeclaringClass()->IsAssignableFrom(c)) {
337 JniAbortF(function_name_, "can't call static %s on class %s",
338 PrettyMethod(m).c_str(), PrettyClass(c).c_str());
339 }
340 }
341
342 /*
343 * Verify that "mid" is appropriate for "jobj".
344 *
345 * Make sure the object is an instance of the method's declaring class.
346 * (Note the mid might point to a declaration in an interface; this
347 * will be handled automatically by the instanceof check.)
348 */
CheckVirtualMethod(jobject java_object,jmethodID mid)349 void CheckVirtualMethod(jobject java_object, jmethodID mid)
350 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
351 mirror::ArtMethod* m = CheckMethodID(mid);
352 if (m == nullptr) {
353 return;
354 }
355 mirror::Object* o = soa_.Decode<mirror::Object*>(java_object);
356 if (o == nullptr) {
357 JniAbortF(function_name_, "can't call %s on null object", PrettyMethod(m).c_str());
358 } else if (!o->InstanceOf(m->GetDeclaringClass())) {
359 JniAbortF(function_name_, "can't call %s on instance of %s",
360 PrettyMethod(m).c_str(), PrettyTypeOf(o).c_str());
361 }
362 }
363
364 /**
365 * The format string is a sequence of the following characters,
366 * and must be followed by arguments of the corresponding types
367 * in the same order.
368 *
369 * Java primitive types:
370 * B - jbyte
371 * C - jchar
372 * D - jdouble
373 * F - jfloat
374 * I - jint
375 * J - jlong
376 * S - jshort
377 * Z - jboolean (shown as true and false)
378 * V - void
379 *
380 * Java reference types:
381 * L - jobject
382 * a - jarray
383 * c - jclass
384 * s - jstring
385 *
386 * JNI types:
387 * b - jboolean (shown as JNI_TRUE and JNI_FALSE)
388 * f - jfieldID
389 * m - jmethodID
390 * p - void*
391 * r - jint (for release mode arguments)
392 * u - const char* (Modified UTF-8)
393 * z - jsize (for lengths; use i if negative values are okay)
394 * v - JavaVM*
395 * E - JNIEnv*
396 * . - no argument; just print "..." (used for varargs JNI calls)
397 *
398 * Use the kFlag_NullableUtf flag where 'u' field(s) are nullable.
399 */
Check(bool entry,const char * fmt0,...)400 void Check(bool entry, const char* fmt0, ...) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
401 va_list ap;
402
403 mirror::ArtMethod* traceMethod = nullptr;
404 if (has_method_ && (!soa_.Vm()->trace.empty() || VLOG_IS_ON(third_party_jni))) {
405 // We need to guard some of the invocation interface's calls: a bad caller might
406 // use DetachCurrentThread or GetEnv on a thread that's not yet attached.
407 Thread* self = Thread::Current();
408 if ((flags_ & kFlag_Invocation) == 0 || self != nullptr) {
409 traceMethod = self->GetCurrentMethod(nullptr);
410 }
411 }
412
413 if (((flags_ & kFlag_ForceTrace) != 0) ||
414 (traceMethod != nullptr && ShouldTrace(soa_.Vm(), traceMethod))) {
415 va_start(ap, fmt0);
416 std::string msg;
417 for (const char* fmt = fmt0; *fmt;) {
418 char ch = *fmt++;
419 if (ch == 'B') { // jbyte
420 jbyte b = va_arg(ap, int);
421 if (b >= 0 && b < 10) {
422 StringAppendF(&msg, "%d", b);
423 } else {
424 StringAppendF(&msg, "%#x (%d)", b, b);
425 }
426 } else if (ch == 'C') { // jchar
427 jchar c = va_arg(ap, int);
428 if (c < 0x7f && c >= ' ') {
429 StringAppendF(&msg, "U+%x ('%c')", c, c);
430 } else {
431 StringAppendF(&msg, "U+%x", c);
432 }
433 } else if (ch == 'F' || ch == 'D') { // jfloat, jdouble
434 StringAppendF(&msg, "%g", va_arg(ap, double));
435 } else if (ch == 'I' || ch == 'S') { // jint, jshort
436 StringAppendF(&msg, "%d", va_arg(ap, int));
437 } else if (ch == 'J') { // jlong
438 StringAppendF(&msg, "%" PRId64, va_arg(ap, jlong));
439 } else if (ch == 'Z') { // jboolean
440 StringAppendF(&msg, "%s", va_arg(ap, int) ? "true" : "false");
441 } else if (ch == 'V') { // void
442 msg += "void";
443 } else if (ch == 'v') { // JavaVM*
444 JavaVM* vm = va_arg(ap, JavaVM*);
445 StringAppendF(&msg, "(JavaVM*)%p", vm);
446 } else if (ch == 'E') { // JNIEnv*
447 JNIEnv* env = va_arg(ap, JNIEnv*);
448 StringAppendF(&msg, "(JNIEnv*)%p", env);
449 } else if (ch == 'L' || ch == 'a' || ch == 's') { // jobject, jarray, jstring
450 // For logging purposes, these are identical.
451 jobject o = va_arg(ap, jobject);
452 if (o == nullptr) {
453 msg += "NULL";
454 } else {
455 StringAppendF(&msg, "%p", o);
456 }
457 } else if (ch == 'b') { // jboolean (JNI-style)
458 jboolean b = va_arg(ap, int);
459 msg += (b ? "JNI_TRUE" : "JNI_FALSE");
460 } else if (ch == 'c') { // jclass
461 jclass jc = va_arg(ap, jclass);
462 mirror::Class* c = reinterpret_cast<mirror::Class*>(Thread::Current()->DecodeJObject(jc));
463 if (c == nullptr) {
464 msg += "NULL";
465 } else if (c == kInvalidIndirectRefObject ||
466 !Runtime::Current()->GetHeap()->IsValidObjectAddress(c)) {
467 StringAppendF(&msg, "INVALID POINTER:%p", jc);
468 } else if (!c->IsClass()) {
469 msg += "INVALID NON-CLASS OBJECT OF TYPE:" + PrettyTypeOf(c);
470 } else {
471 msg += PrettyClass(c);
472 if (!entry) {
473 StringAppendF(&msg, " (%p)", jc);
474 }
475 }
476 } else if (ch == 'f') { // jfieldID
477 jfieldID fid = va_arg(ap, jfieldID);
478 mirror::ArtField* f = reinterpret_cast<mirror::ArtField*>(fid);
479 msg += PrettyField(f);
480 if (!entry) {
481 StringAppendF(&msg, " (%p)", fid);
482 }
483 } else if (ch == 'z') { // non-negative jsize
484 // You might expect jsize to be size_t, but it's not; it's the same as jint.
485 // We only treat this specially so we can do the non-negative check.
486 // TODO: maybe this wasn't worth it?
487 jint i = va_arg(ap, jint);
488 StringAppendF(&msg, "%d", i);
489 } else if (ch == 'm') { // jmethodID
490 jmethodID mid = va_arg(ap, jmethodID);
491 mirror::ArtMethod* m = reinterpret_cast<mirror::ArtMethod*>(mid);
492 msg += PrettyMethod(m);
493 if (!entry) {
494 StringAppendF(&msg, " (%p)", mid);
495 }
496 } else if (ch == 'p') { // void* ("pointer")
497 void* p = va_arg(ap, void*);
498 if (p == nullptr) {
499 msg += "NULL";
500 } else {
501 StringAppendF(&msg, "(void*) %p", p);
502 }
503 } else if (ch == 'r') { // jint (release mode)
504 jint releaseMode = va_arg(ap, jint);
505 if (releaseMode == 0) {
506 msg += "0";
507 } else if (releaseMode == JNI_ABORT) {
508 msg += "JNI_ABORT";
509 } else if (releaseMode == JNI_COMMIT) {
510 msg += "JNI_COMMIT";
511 } else {
512 StringAppendF(&msg, "invalid release mode %d", releaseMode);
513 }
514 } else if (ch == 'u') { // const char* (Modified UTF-8)
515 const char* utf = va_arg(ap, const char*);
516 if (utf == nullptr) {
517 msg += "NULL";
518 } else {
519 StringAppendF(&msg, "\"%s\"", utf);
520 }
521 } else if (ch == '.') {
522 msg += "...";
523 } else {
524 JniAbortF(function_name_, "unknown trace format specifier: %c", ch);
525 return;
526 }
527 if (*fmt) {
528 StringAppendF(&msg, ", ");
529 }
530 }
531 va_end(ap);
532
533 if ((flags_ & kFlag_ForceTrace) != 0) {
534 LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")";
535 } else if (entry) {
536 if (has_method_) {
537 std::string methodName(PrettyMethod(traceMethod, false));
538 LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")";
539 indent_ = methodName.size() + 1;
540 } else {
541 LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")";
542 indent_ = 0;
543 }
544 } else {
545 LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str());
546 }
547 }
548
549 // We always do the thorough checks on entry, and never on exit...
550 if (entry) {
551 va_start(ap, fmt0);
552 for (const char* fmt = fmt0; *fmt; ++fmt) {
553 char ch = *fmt;
554 if (ch == 'a') {
555 CheckArray(va_arg(ap, jarray));
556 } else if (ch == 'c') {
557 CheckInstance(kClass, va_arg(ap, jclass));
558 } else if (ch == 'L') {
559 CheckObject(va_arg(ap, jobject));
560 } else if (ch == 'r') {
561 CheckReleaseMode(va_arg(ap, jint));
562 } else if (ch == 's') {
563 CheckInstance(kString, va_arg(ap, jstring));
564 } else if (ch == 'u') {
565 if ((flags_ & kFlag_Release) != 0) {
566 CheckNonNull(va_arg(ap, const char*));
567 } else {
568 bool nullable = ((flags_ & kFlag_NullableUtf) != 0);
569 CheckUtfString(va_arg(ap, const char*), nullable);
570 }
571 } else if (ch == 'z') {
572 CheckLengthPositive(va_arg(ap, jsize));
573 } else if (strchr("BCISZbfmpEv", ch) != nullptr) {
574 va_arg(ap, uint32_t); // Skip this argument.
575 } else if (ch == 'D' || ch == 'F') {
576 va_arg(ap, double); // Skip this argument.
577 } else if (ch == 'J') {
578 va_arg(ap, uint64_t); // Skip this argument.
579 } else if (ch == '.') {
580 } else {
581 LOG(FATAL) << "Unknown check format specifier: " << ch;
582 }
583 }
584 va_end(ap);
585 }
586 }
587
588 enum InstanceKind {
589 kClass,
590 kDirectByteBuffer,
591 kObject,
592 kString,
593 kThrowable,
594 };
595
596 /*
597 * Verify that "jobj" is a valid non-NULL object reference, and points to
598 * an instance of expectedClass.
599 *
600 * Because we're looking at an object on the GC heap, we have to switch
601 * to "running" mode before doing the checks.
602 */
CheckInstance(InstanceKind kind,jobject java_object)603 bool CheckInstance(InstanceKind kind, jobject java_object)
604 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
605 const char* what = nullptr;
606 switch (kind) {
607 case kClass:
608 what = "jclass";
609 break;
610 case kDirectByteBuffer:
611 what = "direct ByteBuffer";
612 break;
613 case kObject:
614 what = "jobject";
615 break;
616 case kString:
617 what = "jstring";
618 break;
619 case kThrowable:
620 what = "jthrowable";
621 break;
622 default:
623 LOG(FATAL) << "Unknown kind " << static_cast<int>(kind);
624 }
625
626 if (java_object == nullptr) {
627 JniAbortF(function_name_, "%s received null %s", function_name_, what);
628 return false;
629 }
630
631 mirror::Object* obj = soa_.Decode<mirror::Object*>(java_object);
632 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(obj)) {
633 Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
634 JniAbortF(function_name_, "%s is an invalid %s: %p (%p)",
635 what, ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(), java_object, obj);
636 return false;
637 }
638
639 bool okay = true;
640 switch (kind) {
641 case kClass:
642 okay = obj->IsClass();
643 break;
644 case kDirectByteBuffer:
645 UNIMPLEMENTED(FATAL);
646 break;
647 case kString:
648 okay = obj->GetClass()->IsStringClass();
649 break;
650 case kThrowable:
651 okay = obj->GetClass()->IsThrowableClass();
652 break;
653 case kObject:
654 break;
655 }
656 if (!okay) {
657 JniAbortF(function_name_, "%s has wrong type: %s", what, PrettyTypeOf(obj).c_str());
658 return false;
659 }
660
661 return true;
662 }
663
664 private:
665 // Set "has_method" to true if we have a valid thread with a method pointer.
666 // We won't have one before attaching a thread, after detaching a thread, or
667 // when shutting down the runtime.
Init(int flags,const char * functionName,bool has_method)668 void Init(int flags, const char* functionName, bool has_method) {
669 flags_ = flags;
670 function_name_ = functionName;
671 has_method_ = has_method;
672 }
673
674 /*
675 * Verify that "array" is non-NULL and points to an Array object.
676 *
677 * Since we're dealing with objects, switch to "running" mode.
678 */
CheckArray(jarray java_array)679 void CheckArray(jarray java_array) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
680 if (java_array == nullptr) {
681 JniAbortF(function_name_, "jarray was NULL");
682 return;
683 }
684
685 mirror::Array* a = soa_.Decode<mirror::Array*>(java_array);
686 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(a)) {
687 Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
688 JniAbortF(function_name_, "jarray is an invalid %s: %p (%p)",
689 ToStr<IndirectRefKind>(GetIndirectRefKind(java_array)).c_str(), java_array, a);
690 } else if (!a->IsArrayInstance()) {
691 JniAbortF(function_name_, "jarray argument has non-array type: %s", PrettyTypeOf(a).c_str());
692 }
693 }
694
CheckLengthPositive(jsize length)695 void CheckLengthPositive(jsize length) {
696 if (length < 0) {
697 JniAbortF(function_name_, "negative jsize: %d", length);
698 }
699 }
700
CheckFieldID(jfieldID fid)701 mirror::ArtField* CheckFieldID(jfieldID fid) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
702 if (fid == nullptr) {
703 JniAbortF(function_name_, "jfieldID was NULL");
704 return nullptr;
705 }
706 mirror::ArtField* f = soa_.DecodeField(fid);
707 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(f) || !f->IsArtField()) {
708 Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
709 JniAbortF(function_name_, "invalid jfieldID: %p", fid);
710 return nullptr;
711 }
712 return f;
713 }
714
CheckMethodID(jmethodID mid)715 mirror::ArtMethod* CheckMethodID(jmethodID mid) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
716 if (mid == nullptr) {
717 JniAbortF(function_name_, "jmethodID was NULL");
718 return nullptr;
719 }
720 mirror::ArtMethod* m = soa_.DecodeMethod(mid);
721 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(m) || !m->IsArtMethod()) {
722 Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
723 JniAbortF(function_name_, "invalid jmethodID: %p", mid);
724 return nullptr;
725 }
726 return m;
727 }
728
729 /*
730 * Verify that "jobj" is a valid object, and that it's an object that JNI
731 * is allowed to know about. We allow NULL references.
732 *
733 * Switches to "running" mode before performing checks.
734 */
CheckObject(jobject java_object)735 void CheckObject(jobject java_object)
736 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
737 if (java_object == nullptr) {
738 return;
739 }
740
741 mirror::Object* o = soa_.Decode<mirror::Object*>(java_object);
742 if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(o)) {
743 Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
744 // TODO: when we remove work_around_app_jni_bugs, this should be impossible.
745 JniAbortF(function_name_, "native code passing in reference to invalid %s: %p",
746 ToStr<IndirectRefKind>(GetIndirectRefKind(java_object)).c_str(), java_object);
747 }
748 }
749
750 /*
751 * Verify that the "mode" argument passed to a primitive array Release
752 * function is one of the valid values.
753 */
CheckReleaseMode(jint mode)754 void CheckReleaseMode(jint mode) {
755 if (mode != 0 && mode != JNI_COMMIT && mode != JNI_ABORT) {
756 JniAbortF(function_name_, "unknown value for release mode: %d", mode);
757 }
758 }
759
CheckThread(int flags)760 void CheckThread(int flags) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
761 Thread* self = Thread::Current();
762 if (self == nullptr) {
763 JniAbortF(function_name_, "a thread (tid %d) is making JNI calls without being attached", GetTid());
764 return;
765 }
766
767 // Get the *correct* JNIEnv by going through our TLS pointer.
768 JNIEnvExt* threadEnv = self->GetJniEnv();
769
770 // Verify that the current thread is (a) attached and (b) associated with
771 // this particular instance of JNIEnv.
772 if (soa_.Env() != threadEnv) {
773 JniAbortF(function_name_, "thread %s using JNIEnv* from thread %s",
774 ToStr<Thread>(*self).c_str(), ToStr<Thread>(*soa_.Self()).c_str());
775 return;
776 }
777
778 // Verify that, if this thread previously made a critical "get" call, we
779 // do the corresponding "release" call before we try anything else.
780 switch (flags & kFlag_CritMask) {
781 case kFlag_CritOkay: // okay to call this method
782 break;
783 case kFlag_CritBad: // not okay to call
784 if (threadEnv->critical) {
785 JniAbortF(function_name_, "thread %s using JNI after critical get", ToStr<Thread>(*self).c_str());
786 return;
787 }
788 break;
789 case kFlag_CritGet: // this is a "get" call
790 // Don't check here; we allow nested gets.
791 threadEnv->critical++;
792 break;
793 case kFlag_CritRelease: // this is a "release" call
794 threadEnv->critical--;
795 if (threadEnv->critical < 0) {
796 JniAbortF(function_name_, "thread %s called too many critical releases", ToStr<Thread>(*self).c_str());
797 return;
798 }
799 break;
800 default:
801 LOG(FATAL) << "Bad flags (internal error): " << flags;
802 }
803
804 // Verify that, if an exception has been raised, the native code doesn't
805 // make any JNI calls other than the Exception* methods.
806 if ((flags & kFlag_ExcepOkay) == 0 && self->IsExceptionPending()) {
807 ThrowLocation throw_location;
808 mirror::Throwable* exception = self->GetException(&throw_location);
809 std::string type(PrettyTypeOf(exception));
810 JniAbortF(function_name_, "JNI %s called with pending exception '%s' thrown in %s",
811 function_name_, type.c_str(), throw_location.Dump().c_str());
812 return;
813 }
814 }
815
816 // Verifies that "bytes" points to valid Modified UTF-8 data.
CheckUtfString(const char * bytes,bool nullable)817 void CheckUtfString(const char* bytes, bool nullable) {
818 if (bytes == nullptr) {
819 if (!nullable) {
820 JniAbortF(function_name_, "non-nullable const char* was NULL");
821 return;
822 }
823 return;
824 }
825
826 const char* errorKind = nullptr;
827 uint8_t utf8 = CheckUtfBytes(bytes, &errorKind);
828 if (errorKind != nullptr) {
829 JniAbortF(function_name_,
830 "input is not valid Modified UTF-8: illegal %s byte %#x\n"
831 " string: '%s'", errorKind, utf8, bytes);
832 return;
833 }
834 }
835
CheckUtfBytes(const char * bytes,const char ** errorKind)836 static uint8_t CheckUtfBytes(const char* bytes, const char** errorKind) {
837 while (*bytes != '\0') {
838 uint8_t utf8 = *(bytes++);
839 // Switch on the high four bits.
840 switch (utf8 >> 4) {
841 case 0x00:
842 case 0x01:
843 case 0x02:
844 case 0x03:
845 case 0x04:
846 case 0x05:
847 case 0x06:
848 case 0x07:
849 // Bit pattern 0xxx. No need for any extra bytes.
850 break;
851 case 0x08:
852 case 0x09:
853 case 0x0a:
854 case 0x0b:
855 case 0x0f:
856 /*
857 * Bit pattern 10xx or 1111, which are illegal start bytes.
858 * Note: 1111 is valid for normal UTF-8, but not the
859 * Modified UTF-8 used here.
860 */
861 *errorKind = "start";
862 return utf8;
863 case 0x0e:
864 // Bit pattern 1110, so there are two additional bytes.
865 utf8 = *(bytes++);
866 if ((utf8 & 0xc0) != 0x80) {
867 *errorKind = "continuation";
868 return utf8;
869 }
870 // Fall through to take care of the final byte.
871 case 0x0c:
872 case 0x0d:
873 // Bit pattern 110x, so there is one additional byte.
874 utf8 = *(bytes++);
875 if ((utf8 & 0xc0) != 0x80) {
876 *errorKind = "continuation";
877 return utf8;
878 }
879 break;
880 }
881 }
882 return 0;
883 }
884
885 const ScopedObjectAccess soa_;
886 const char* function_name_;
887 int flags_;
888 bool has_method_;
889 int indent_;
890
891 DISALLOW_COPY_AND_ASSIGN(ScopedCheck);
892 };
893
894 #define CHECK_JNI_ENTRY(flags, types, args...) \
895 ScopedCheck sc(env, flags, __FUNCTION__); \
896 sc.Check(true, types, ##args)
897
898 #define CHECK_JNI_EXIT(type, exp) ({ \
899 auto _rc = (exp); \
900 sc.Check(false, type, _rc); \
901 _rc; })
902 #define CHECK_JNI_EXIT_VOID() \
903 sc.Check(false, "V")
904
905 /*
906 * ===========================================================================
907 * Guarded arrays
908 * ===========================================================================
909 */
910
911 #define kGuardLen 512 /* must be multiple of 2 */
912 #define kGuardPattern 0xd5e3 /* uncommon values; d5e3d5e3 invalid addr */
913 #define kGuardMagic 0xffd5aa96
914
915 /* this gets tucked in at the start of the buffer; struct size must be even */
916 struct GuardedCopy {
917 uint32_t magic;
918 uLong adler;
919 size_t original_length;
920 const void* original_ptr;
921
922 /* find the GuardedCopy given the pointer into the "live" data */
FromDataart::GuardedCopy923 static inline const GuardedCopy* FromData(const void* dataBuf) {
924 return reinterpret_cast<const GuardedCopy*>(ActualBuffer(dataBuf));
925 }
926
927 /*
928 * Create an over-sized buffer to hold the contents of "buf". Copy it in,
929 * filling in the area around it with guard data.
930 *
931 * We use a 16-bit pattern to make a rogue memset less likely to elude us.
932 */
Createart::GuardedCopy933 static void* Create(const void* buf, size_t len, bool modOkay) {
934 size_t newLen = ActualLength(len);
935 uint8_t* newBuf = DebugAlloc(newLen);
936
937 // Fill it in with a pattern.
938 uint16_t* pat = reinterpret_cast<uint16_t*>(newBuf);
939 for (size_t i = 0; i < newLen / 2; i++) {
940 *pat++ = kGuardPattern;
941 }
942
943 // Copy the data in; note "len" could be zero.
944 memcpy(newBuf + kGuardLen / 2, buf, len);
945
946 // If modification is not expected, grab a checksum.
947 uLong adler = 0;
948 if (!modOkay) {
949 adler = adler32(0L, Z_NULL, 0);
950 adler = adler32(adler, reinterpret_cast<const Bytef*>(buf), len);
951 *reinterpret_cast<uLong*>(newBuf) = adler;
952 }
953
954 GuardedCopy* pExtra = reinterpret_cast<GuardedCopy*>(newBuf);
955 pExtra->magic = kGuardMagic;
956 pExtra->adler = adler;
957 pExtra->original_ptr = buf;
958 pExtra->original_length = len;
959
960 return newBuf + kGuardLen / 2;
961 }
962
963 /*
964 * Free up the guard buffer, scrub it, and return the original pointer.
965 */
Destroyart::GuardedCopy966 static void* Destroy(void* dataBuf) {
967 const GuardedCopy* pExtra = GuardedCopy::FromData(dataBuf);
968 void* original_ptr = const_cast<void*>(pExtra->original_ptr);
969 size_t len = pExtra->original_length;
970 DebugFree(dataBuf, len);
971 return original_ptr;
972 }
973
974 /*
975 * Verify the guard area and, if "modOkay" is false, that the data itself
976 * has not been altered.
977 *
978 * The caller has already checked that "dataBuf" is non-NULL.
979 */
Checkart::GuardedCopy980 static void Check(const char* functionName, const void* dataBuf, bool modOkay) {
981 static const uint32_t kMagicCmp = kGuardMagic;
982 const uint8_t* fullBuf = ActualBuffer(dataBuf);
983 const GuardedCopy* pExtra = GuardedCopy::FromData(dataBuf);
984
985 // Before we do anything with "pExtra", check the magic number. We
986 // do the check with memcmp rather than "==" in case the pointer is
987 // unaligned. If it points to completely bogus memory we're going
988 // to crash, but there's no easy way around that.
989 if (memcmp(&pExtra->magic, &kMagicCmp, 4) != 0) {
990 uint8_t buf[4];
991 memcpy(buf, &pExtra->magic, 4);
992 JniAbortF(functionName,
993 "guard magic does not match (found 0x%02x%02x%02x%02x) -- incorrect data pointer %p?",
994 buf[3], buf[2], buf[1], buf[0], dataBuf); // Assumes little-endian.
995 }
996
997 size_t len = pExtra->original_length;
998
999 // Check bottom half of guard; skip over optional checksum storage.
1000 const uint16_t* pat = reinterpret_cast<const uint16_t*>(fullBuf);
1001 for (size_t i = sizeof(GuardedCopy) / 2; i < (kGuardLen / 2 - sizeof(GuardedCopy)) / 2; i++) {
1002 if (pat[i] != kGuardPattern) {
1003 JniAbortF(functionName, "guard pattern(1) disturbed at %p +%zd", fullBuf, i*2);
1004 }
1005 }
1006
1007 int offset = kGuardLen / 2 + len;
1008 if (offset & 0x01) {
1009 // Odd byte; expected value depends on endian.
1010 const uint16_t patSample = kGuardPattern;
1011 uint8_t expected_byte = reinterpret_cast<const uint8_t*>(&patSample)[1];
1012 if (fullBuf[offset] != expected_byte) {
1013 JniAbortF(functionName, "guard pattern disturbed in odd byte after %p +%d 0x%02x 0x%02x",
1014 fullBuf, offset, fullBuf[offset], expected_byte);
1015 }
1016 offset++;
1017 }
1018
1019 // Check top half of guard.
1020 pat = reinterpret_cast<const uint16_t*>(fullBuf + offset);
1021 for (size_t i = 0; i < kGuardLen / 4; i++) {
1022 if (pat[i] != kGuardPattern) {
1023 JniAbortF(functionName, "guard pattern(2) disturbed at %p +%zd", fullBuf, offset + i*2);
1024 }
1025 }
1026
1027 // If modification is not expected, verify checksum. Strictly speaking
1028 // this is wrong: if we told the client that we made a copy, there's no
1029 // reason they can't alter the buffer.
1030 if (!modOkay) {
1031 uLong adler = adler32(0L, Z_NULL, 0);
1032 adler = adler32(adler, (const Bytef*)dataBuf, len);
1033 if (pExtra->adler != adler) {
1034 JniAbortF(functionName, "buffer modified (0x%08lx vs 0x%08lx) at address %p",
1035 pExtra->adler, adler, dataBuf);
1036 }
1037 }
1038 }
1039
1040 private:
DebugAllocart::GuardedCopy1041 static uint8_t* DebugAlloc(size_t len) {
1042 void* result = mmap(nullptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
1043 if (result == MAP_FAILED) {
1044 PLOG(FATAL) << "GuardedCopy::create mmap(" << len << ") failed";
1045 }
1046 return reinterpret_cast<uint8_t*>(result);
1047 }
1048
DebugFreeart::GuardedCopy1049 static void DebugFree(void* dataBuf, size_t len) {
1050 uint8_t* fullBuf = ActualBuffer(dataBuf);
1051 size_t totalByteCount = ActualLength(len);
1052 // TODO: we could mprotect instead, and keep the allocation around for a while.
1053 // This would be even more expensive, but it might catch more errors.
1054 // if (mprotect(fullBuf, totalByteCount, PROT_NONE) != 0) {
1055 // PLOG(WARNING) << "mprotect(PROT_NONE) failed";
1056 // }
1057 if (munmap(fullBuf, totalByteCount) != 0) {
1058 PLOG(FATAL) << "munmap(" << reinterpret_cast<void*>(fullBuf) << ", " << totalByteCount << ") failed";
1059 }
1060 }
1061
ActualBufferart::GuardedCopy1062 static const uint8_t* ActualBuffer(const void* dataBuf) {
1063 return reinterpret_cast<const uint8_t*>(dataBuf) - kGuardLen / 2;
1064 }
1065
ActualBufferart::GuardedCopy1066 static uint8_t* ActualBuffer(void* dataBuf) {
1067 return reinterpret_cast<uint8_t*>(dataBuf) - kGuardLen / 2;
1068 }
1069
1070 // Underlying length of a user allocation of 'length' bytes.
ActualLengthart::GuardedCopy1071 static size_t ActualLength(size_t length) {
1072 return (length + kGuardLen + 1) & ~0x01;
1073 }
1074 };
1075
1076 /*
1077 * Create a guarded copy of a primitive array. Modifications to the copied
1078 * data are allowed. Returns a pointer to the copied data.
1079 */
CreateGuardedPACopy(JNIEnv * env,const jarray java_array,jboolean * isCopy)1080 static void* CreateGuardedPACopy(JNIEnv* env, const jarray java_array, jboolean* isCopy) {
1081 ScopedObjectAccess soa(env);
1082
1083 mirror::Array* a = soa.Decode<mirror::Array*>(java_array);
1084 size_t component_size = a->GetClass()->GetComponentSize();
1085 size_t byte_count = a->GetLength() * component_size;
1086 void* result = GuardedCopy::Create(a->GetRawData(component_size, 0), byte_count, true);
1087 if (isCopy != nullptr) {
1088 *isCopy = JNI_TRUE;
1089 }
1090 return result;
1091 }
1092
1093 /*
1094 * Perform the array "release" operation, which may or may not copy data
1095 * back into the managed heap, and may or may not release the underlying storage.
1096 */
ReleaseGuardedPACopy(JNIEnv * env,jarray java_array,void * dataBuf,int mode)1097 static void ReleaseGuardedPACopy(JNIEnv* env, jarray java_array, void* dataBuf, int mode) {
1098 ScopedObjectAccess soa(env);
1099 mirror::Array* a = soa.Decode<mirror::Array*>(java_array);
1100
1101 GuardedCopy::Check(__FUNCTION__, dataBuf, true);
1102
1103 if (mode != JNI_ABORT) {
1104 size_t len = GuardedCopy::FromData(dataBuf)->original_length;
1105 memcpy(a->GetRawData(a->GetClass()->GetComponentSize(), 0), dataBuf, len);
1106 }
1107 if (mode != JNI_COMMIT) {
1108 GuardedCopy::Destroy(dataBuf);
1109 }
1110 }
1111
1112 /*
1113 * ===========================================================================
1114 * JNI functions
1115 * ===========================================================================
1116 */
1117
1118 class CheckJNI {
1119 public:
GetVersion(JNIEnv * env)1120 static jint GetVersion(JNIEnv* env) {
1121 CHECK_JNI_ENTRY(kFlag_Default, "E", env);
1122 return CHECK_JNI_EXIT("I", baseEnv(env)->GetVersion(env));
1123 }
1124
DefineClass(JNIEnv * env,const char * name,jobject loader,const jbyte * buf,jsize bufLen)1125 static jclass DefineClass(JNIEnv* env, const char* name, jobject loader, const jbyte* buf, jsize bufLen) {
1126 CHECK_JNI_ENTRY(kFlag_Default, "EuLpz", env, name, loader, buf, bufLen);
1127 sc.CheckClassName(name);
1128 return CHECK_JNI_EXIT("c", baseEnv(env)->DefineClass(env, name, loader, buf, bufLen));
1129 }
1130
FindClass(JNIEnv * env,const char * name)1131 static jclass FindClass(JNIEnv* env, const char* name) {
1132 CHECK_JNI_ENTRY(kFlag_Default, "Eu", env, name);
1133 sc.CheckClassName(name);
1134 return CHECK_JNI_EXIT("c", baseEnv(env)->FindClass(env, name));
1135 }
1136
GetSuperclass(JNIEnv * env,jclass c)1137 static jclass GetSuperclass(JNIEnv* env, jclass c) {
1138 CHECK_JNI_ENTRY(kFlag_Default, "Ec", env, c);
1139 return CHECK_JNI_EXIT("c", baseEnv(env)->GetSuperclass(env, c));
1140 }
1141
IsAssignableFrom(JNIEnv * env,jclass c1,jclass c2)1142 static jboolean IsAssignableFrom(JNIEnv* env, jclass c1, jclass c2) {
1143 CHECK_JNI_ENTRY(kFlag_Default, "Ecc", env, c1, c2);
1144 return CHECK_JNI_EXIT("b", baseEnv(env)->IsAssignableFrom(env, c1, c2));
1145 }
1146
FromReflectedMethod(JNIEnv * env,jobject method)1147 static jmethodID FromReflectedMethod(JNIEnv* env, jobject method) {
1148 CHECK_JNI_ENTRY(kFlag_Default, "EL", env, method);
1149 // TODO: check that 'field' is a java.lang.reflect.Method.
1150 return CHECK_JNI_EXIT("m", baseEnv(env)->FromReflectedMethod(env, method));
1151 }
1152
FromReflectedField(JNIEnv * env,jobject field)1153 static jfieldID FromReflectedField(JNIEnv* env, jobject field) {
1154 CHECK_JNI_ENTRY(kFlag_Default, "EL", env, field);
1155 // TODO: check that 'field' is a java.lang.reflect.Field.
1156 return CHECK_JNI_EXIT("f", baseEnv(env)->FromReflectedField(env, field));
1157 }
1158
ToReflectedMethod(JNIEnv * env,jclass cls,jmethodID mid,jboolean isStatic)1159 static jobject ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID mid, jboolean isStatic) {
1160 CHECK_JNI_ENTRY(kFlag_Default, "Ecmb", env, cls, mid, isStatic);
1161 return CHECK_JNI_EXIT("L", baseEnv(env)->ToReflectedMethod(env, cls, mid, isStatic));
1162 }
1163
ToReflectedField(JNIEnv * env,jclass cls,jfieldID fid,jboolean isStatic)1164 static jobject ToReflectedField(JNIEnv* env, jclass cls, jfieldID fid, jboolean isStatic) {
1165 CHECK_JNI_ENTRY(kFlag_Default, "Ecfb", env, cls, fid, isStatic);
1166 return CHECK_JNI_EXIT("L", baseEnv(env)->ToReflectedField(env, cls, fid, isStatic));
1167 }
1168
Throw(JNIEnv * env,jthrowable obj)1169 static jint Throw(JNIEnv* env, jthrowable obj) {
1170 CHECK_JNI_ENTRY(kFlag_Default, "EL", env, obj);
1171 // TODO: check that 'obj' is a java.lang.Throwable.
1172 return CHECK_JNI_EXIT("I", baseEnv(env)->Throw(env, obj));
1173 }
1174
ThrowNew(JNIEnv * env,jclass c,const char * message)1175 static jint ThrowNew(JNIEnv* env, jclass c, const char* message) {
1176 CHECK_JNI_ENTRY(kFlag_NullableUtf, "Ecu", env, c, message);
1177 return CHECK_JNI_EXIT("I", baseEnv(env)->ThrowNew(env, c, message));
1178 }
1179
ExceptionOccurred(JNIEnv * env)1180 static jthrowable ExceptionOccurred(JNIEnv* env) {
1181 CHECK_JNI_ENTRY(kFlag_ExcepOkay, "E", env);
1182 return CHECK_JNI_EXIT("L", baseEnv(env)->ExceptionOccurred(env));
1183 }
1184
ExceptionDescribe(JNIEnv * env)1185 static void ExceptionDescribe(JNIEnv* env) {
1186 CHECK_JNI_ENTRY(kFlag_ExcepOkay, "E", env);
1187 baseEnv(env)->ExceptionDescribe(env);
1188 CHECK_JNI_EXIT_VOID();
1189 }
1190
ExceptionClear(JNIEnv * env)1191 static void ExceptionClear(JNIEnv* env) {
1192 CHECK_JNI_ENTRY(kFlag_ExcepOkay, "E", env);
1193 baseEnv(env)->ExceptionClear(env);
1194 CHECK_JNI_EXIT_VOID();
1195 }
1196
FatalError(JNIEnv * env,const char * msg)1197 static void FatalError(JNIEnv* env, const char* msg) {
1198 // The JNI specification doesn't say it's okay to call FatalError with a pending exception,
1199 // but you're about to abort anyway, and it's quite likely that you have a pending exception,
1200 // and it's not unimaginable that you don't know that you do. So we allow it.
1201 CHECK_JNI_ENTRY(kFlag_ExcepOkay | kFlag_NullableUtf, "Eu", env, msg);
1202 baseEnv(env)->FatalError(env, msg);
1203 CHECK_JNI_EXIT_VOID();
1204 }
1205
PushLocalFrame(JNIEnv * env,jint capacity)1206 static jint PushLocalFrame(JNIEnv* env, jint capacity) {
1207 CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "EI", env, capacity);
1208 return CHECK_JNI_EXIT("I", baseEnv(env)->PushLocalFrame(env, capacity));
1209 }
1210
PopLocalFrame(JNIEnv * env,jobject res)1211 static jobject PopLocalFrame(JNIEnv* env, jobject res) {
1212 CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "EL", env, res);
1213 return CHECK_JNI_EXIT("L", baseEnv(env)->PopLocalFrame(env, res));
1214 }
1215
NewGlobalRef(JNIEnv * env,jobject obj)1216 static jobject NewGlobalRef(JNIEnv* env, jobject obj) {
1217 CHECK_JNI_ENTRY(kFlag_Default, "EL", env, obj);
1218 return CHECK_JNI_EXIT("L", baseEnv(env)->NewGlobalRef(env, obj));
1219 }
1220
NewLocalRef(JNIEnv * env,jobject ref)1221 static jobject NewLocalRef(JNIEnv* env, jobject ref) {
1222 CHECK_JNI_ENTRY(kFlag_Default, "EL", env, ref);
1223 return CHECK_JNI_EXIT("L", baseEnv(env)->NewLocalRef(env, ref));
1224 }
1225
DeleteGlobalRef(JNIEnv * env,jobject globalRef)1226 static void DeleteGlobalRef(JNIEnv* env, jobject globalRef) {
1227 CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "EL", env, globalRef);
1228 if (globalRef != nullptr && GetIndirectRefKind(globalRef) != kGlobal) {
1229 JniAbortF(__FUNCTION__, "DeleteGlobalRef on %s: %p",
1230 ToStr<IndirectRefKind>(GetIndirectRefKind(globalRef)).c_str(), globalRef);
1231 } else {
1232 baseEnv(env)->DeleteGlobalRef(env, globalRef);
1233 CHECK_JNI_EXIT_VOID();
1234 }
1235 }
1236
DeleteWeakGlobalRef(JNIEnv * env,jweak weakGlobalRef)1237 static void DeleteWeakGlobalRef(JNIEnv* env, jweak weakGlobalRef) {
1238 CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "EL", env, weakGlobalRef);
1239 if (weakGlobalRef != nullptr && GetIndirectRefKind(weakGlobalRef) != kWeakGlobal) {
1240 JniAbortF(__FUNCTION__, "DeleteWeakGlobalRef on %s: %p",
1241 ToStr<IndirectRefKind>(GetIndirectRefKind(weakGlobalRef)).c_str(), weakGlobalRef);
1242 } else {
1243 baseEnv(env)->DeleteWeakGlobalRef(env, weakGlobalRef);
1244 CHECK_JNI_EXIT_VOID();
1245 }
1246 }
1247
DeleteLocalRef(JNIEnv * env,jobject localRef)1248 static void DeleteLocalRef(JNIEnv* env, jobject localRef) {
1249 CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "EL", env, localRef);
1250 if (localRef != nullptr && GetIndirectRefKind(localRef) != kLocal && !IsHandleScopeLocalRef(env, localRef)) {
1251 JniAbortF(__FUNCTION__, "DeleteLocalRef on %s: %p",
1252 ToStr<IndirectRefKind>(GetIndirectRefKind(localRef)).c_str(), localRef);
1253 } else {
1254 baseEnv(env)->DeleteLocalRef(env, localRef);
1255 CHECK_JNI_EXIT_VOID();
1256 }
1257 }
1258
EnsureLocalCapacity(JNIEnv * env,jint capacity)1259 static jint EnsureLocalCapacity(JNIEnv *env, jint capacity) {
1260 CHECK_JNI_ENTRY(kFlag_Default, "EI", env, capacity);
1261 return CHECK_JNI_EXIT("I", baseEnv(env)->EnsureLocalCapacity(env, capacity));
1262 }
1263
IsSameObject(JNIEnv * env,jobject ref1,jobject ref2)1264 static jboolean IsSameObject(JNIEnv* env, jobject ref1, jobject ref2) {
1265 CHECK_JNI_ENTRY(kFlag_Default, "ELL", env, ref1, ref2);
1266 return CHECK_JNI_EXIT("b", baseEnv(env)->IsSameObject(env, ref1, ref2));
1267 }
1268
AllocObject(JNIEnv * env,jclass c)1269 static jobject AllocObject(JNIEnv* env, jclass c) {
1270 CHECK_JNI_ENTRY(kFlag_Default, "Ec", env, c);
1271 return CHECK_JNI_EXIT("L", baseEnv(env)->AllocObject(env, c));
1272 }
1273
NewObject(JNIEnv * env,jclass c,jmethodID mid,...)1274 static jobject NewObject(JNIEnv* env, jclass c, jmethodID mid, ...) {
1275 CHECK_JNI_ENTRY(kFlag_Default, "Ecm.", env, c, mid);
1276 va_list args;
1277 va_start(args, mid);
1278 jobject result = baseEnv(env)->NewObjectV(env, c, mid, args);
1279 va_end(args);
1280 return CHECK_JNI_EXIT("L", result);
1281 }
1282
NewObjectV(JNIEnv * env,jclass c,jmethodID mid,va_list args)1283 static jobject NewObjectV(JNIEnv* env, jclass c, jmethodID mid, va_list args) {
1284 CHECK_JNI_ENTRY(kFlag_Default, "Ecm.", env, c, mid);
1285 return CHECK_JNI_EXIT("L", baseEnv(env)->NewObjectV(env, c, mid, args));
1286 }
1287
NewObjectA(JNIEnv * env,jclass c,jmethodID mid,jvalue * args)1288 static jobject NewObjectA(JNIEnv* env, jclass c, jmethodID mid, jvalue* args) {
1289 CHECK_JNI_ENTRY(kFlag_Default, "Ecm.", env, c, mid);
1290 return CHECK_JNI_EXIT("L", baseEnv(env)->NewObjectA(env, c, mid, args));
1291 }
1292
GetObjectClass(JNIEnv * env,jobject obj)1293 static jclass GetObjectClass(JNIEnv* env, jobject obj) {
1294 CHECK_JNI_ENTRY(kFlag_Default, "EL", env, obj);
1295 return CHECK_JNI_EXIT("c", baseEnv(env)->GetObjectClass(env, obj));
1296 }
1297
IsInstanceOf(JNIEnv * env,jobject obj,jclass c)1298 static jboolean IsInstanceOf(JNIEnv* env, jobject obj, jclass c) {
1299 CHECK_JNI_ENTRY(kFlag_Default, "ELc", env, obj, c);
1300 return CHECK_JNI_EXIT("b", baseEnv(env)->IsInstanceOf(env, obj, c));
1301 }
1302
GetMethodID(JNIEnv * env,jclass c,const char * name,const char * sig)1303 static jmethodID GetMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
1304 CHECK_JNI_ENTRY(kFlag_Default, "Ecuu", env, c, name, sig);
1305 return CHECK_JNI_EXIT("m", baseEnv(env)->GetMethodID(env, c, name, sig));
1306 }
1307
GetFieldID(JNIEnv * env,jclass c,const char * name,const char * sig)1308 static jfieldID GetFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
1309 CHECK_JNI_ENTRY(kFlag_Default, "Ecuu", env, c, name, sig);
1310 return CHECK_JNI_EXIT("f", baseEnv(env)->GetFieldID(env, c, name, sig));
1311 }
1312
GetStaticMethodID(JNIEnv * env,jclass c,const char * name,const char * sig)1313 static jmethodID GetStaticMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
1314 CHECK_JNI_ENTRY(kFlag_Default, "Ecuu", env, c, name, sig);
1315 return CHECK_JNI_EXIT("m", baseEnv(env)->GetStaticMethodID(env, c, name, sig));
1316 }
1317
GetStaticFieldID(JNIEnv * env,jclass c,const char * name,const char * sig)1318 static jfieldID GetStaticFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
1319 CHECK_JNI_ENTRY(kFlag_Default, "Ecuu", env, c, name, sig);
1320 return CHECK_JNI_EXIT("f", baseEnv(env)->GetStaticFieldID(env, c, name, sig));
1321 }
1322
1323 #define FIELD_ACCESSORS(_ctype, _jname, _jvalue_type, _type) \
1324 static _ctype GetStatic##_jname##Field(JNIEnv* env, jclass c, jfieldID fid) { \
1325 CHECK_JNI_ENTRY(kFlag_Default, "Ecf", env, c, fid); \
1326 sc.CheckStaticFieldID(c, fid); \
1327 return CHECK_JNI_EXIT(_type, baseEnv(env)->GetStatic##_jname##Field(env, c, fid)); \
1328 } \
1329 static _ctype Get##_jname##Field(JNIEnv* env, jobject obj, jfieldID fid) { \
1330 CHECK_JNI_ENTRY(kFlag_Default, "ELf", env, obj, fid); \
1331 sc.CheckInstanceFieldID(obj, fid); \
1332 return CHECK_JNI_EXIT(_type, baseEnv(env)->Get##_jname##Field(env, obj, fid)); \
1333 } \
1334 static void SetStatic##_jname##Field(JNIEnv* env, jclass c, jfieldID fid, _ctype value) { \
1335 CHECK_JNI_ENTRY(kFlag_Default, "Ecf" _type, env, c, fid, value); \
1336 sc.CheckStaticFieldID(c, fid); \
1337 /* "value" arg only used when type == ref */ \
1338 jvalue java_type_value; \
1339 java_type_value._jvalue_type = value; \
1340 sc.CheckFieldType(java_type_value, fid, _type[0], true); \
1341 baseEnv(env)->SetStatic##_jname##Field(env, c, fid, value); \
1342 CHECK_JNI_EXIT_VOID(); \
1343 } \
1344 static void Set##_jname##Field(JNIEnv* env, jobject obj, jfieldID fid, _ctype value) { \
1345 CHECK_JNI_ENTRY(kFlag_Default, "ELf" _type, env, obj, fid, value); \
1346 sc.CheckInstanceFieldID(obj, fid); \
1347 /* "value" arg only used when type == ref */ \
1348 jvalue java_type_value; \
1349 java_type_value._jvalue_type = value; \
1350 sc.CheckFieldType(java_type_value, fid, _type[0], false); \
1351 baseEnv(env)->Set##_jname##Field(env, obj, fid, value); \
1352 CHECK_JNI_EXIT_VOID(); \
1353 }
1354
1355 FIELD_ACCESSORS(jobject, Object, l, "L");
1356 FIELD_ACCESSORS(jboolean, Boolean, z, "Z");
1357 FIELD_ACCESSORS(jbyte, Byte, b, "B");
1358 FIELD_ACCESSORS(jchar, Char, c, "C");
1359 FIELD_ACCESSORS(jshort, Short, s, "S");
1360 FIELD_ACCESSORS(jint, Int, i, "I");
1361 FIELD_ACCESSORS(jlong, Long, j, "J");
1362 FIELD_ACCESSORS(jfloat, Float, f, "F");
1363 FIELD_ACCESSORS(jdouble, Double, d, "D");
1364
1365 #define CALL(_ctype, _jname, _retdecl, _retasgn, _retok, _retsig) \
1366 /* Virtual... */ \
1367 static _ctype Call##_jname##Method(JNIEnv* env, jobject obj, \
1368 jmethodID mid, ...) \
1369 { \
1370 CHECK_JNI_ENTRY(kFlag_Default, "ELm.", env, obj, mid); /* TODO: args! */ \
1371 sc.CheckSig(mid, _retsig, false); \
1372 sc.CheckVirtualMethod(obj, mid); \
1373 _retdecl; \
1374 va_list args; \
1375 va_start(args, mid); \
1376 _retasgn(baseEnv(env)->Call##_jname##MethodV(env, obj, mid, args)); \
1377 va_end(args); \
1378 _retok; \
1379 } \
1380 static _ctype Call##_jname##MethodV(JNIEnv* env, jobject obj, \
1381 jmethodID mid, va_list args) \
1382 { \
1383 CHECK_JNI_ENTRY(kFlag_Default, "ELm.", env, obj, mid); /* TODO: args! */ \
1384 sc.CheckSig(mid, _retsig, false); \
1385 sc.CheckVirtualMethod(obj, mid); \
1386 _retdecl; \
1387 _retasgn(baseEnv(env)->Call##_jname##MethodV(env, obj, mid, args)); \
1388 _retok; \
1389 } \
1390 static _ctype Call##_jname##MethodA(JNIEnv* env, jobject obj, \
1391 jmethodID mid, jvalue* args) \
1392 { \
1393 CHECK_JNI_ENTRY(kFlag_Default, "ELm.", env, obj, mid); /* TODO: args! */ \
1394 sc.CheckSig(mid, _retsig, false); \
1395 sc.CheckVirtualMethod(obj, mid); \
1396 _retdecl; \
1397 _retasgn(baseEnv(env)->Call##_jname##MethodA(env, obj, mid, args)); \
1398 _retok; \
1399 } \
1400 /* Non-virtual... */ \
1401 static _ctype CallNonvirtual##_jname##Method(JNIEnv* env, \
1402 jobject obj, jclass c, jmethodID mid, ...) \
1403 { \
1404 CHECK_JNI_ENTRY(kFlag_Default, "ELcm.", env, obj, c, mid); /* TODO: args! */ \
1405 sc.CheckSig(mid, _retsig, false); \
1406 sc.CheckVirtualMethod(obj, mid); \
1407 _retdecl; \
1408 va_list args; \
1409 va_start(args, mid); \
1410 _retasgn(baseEnv(env)->CallNonvirtual##_jname##MethodV(env, obj, c, mid, args)); \
1411 va_end(args); \
1412 _retok; \
1413 } \
1414 static _ctype CallNonvirtual##_jname##MethodV(JNIEnv* env, \
1415 jobject obj, jclass c, jmethodID mid, va_list args) \
1416 { \
1417 CHECK_JNI_ENTRY(kFlag_Default, "ELcm.", env, obj, c, mid); /* TODO: args! */ \
1418 sc.CheckSig(mid, _retsig, false); \
1419 sc.CheckVirtualMethod(obj, mid); \
1420 _retdecl; \
1421 _retasgn(baseEnv(env)->CallNonvirtual##_jname##MethodV(env, obj, c, mid, args)); \
1422 _retok; \
1423 } \
1424 static _ctype CallNonvirtual##_jname##MethodA(JNIEnv* env, \
1425 jobject obj, jclass c, jmethodID mid, jvalue* args) \
1426 { \
1427 CHECK_JNI_ENTRY(kFlag_Default, "ELcm.", env, obj, c, mid); /* TODO: args! */ \
1428 sc.CheckSig(mid, _retsig, false); \
1429 sc.CheckVirtualMethod(obj, mid); \
1430 _retdecl; \
1431 _retasgn(baseEnv(env)->CallNonvirtual##_jname##MethodA(env, obj, c, mid, args)); \
1432 _retok; \
1433 } \
1434 /* Static... */ \
1435 static _ctype CallStatic##_jname##Method(JNIEnv* env, jclass c, jmethodID mid, ...) \
1436 { \
1437 CHECK_JNI_ENTRY(kFlag_Default, "Ecm.", env, c, mid); /* TODO: args! */ \
1438 sc.CheckSig(mid, _retsig, true); \
1439 sc.CheckStaticMethod(c, mid); \
1440 _retdecl; \
1441 va_list args; \
1442 va_start(args, mid); \
1443 _retasgn(baseEnv(env)->CallStatic##_jname##MethodV(env, c, mid, args)); \
1444 va_end(args); \
1445 _retok; \
1446 } \
1447 static _ctype CallStatic##_jname##MethodV(JNIEnv* env, jclass c, jmethodID mid, va_list args) \
1448 { \
1449 CHECK_JNI_ENTRY(kFlag_Default, "Ecm.", env, c, mid); /* TODO: args! */ \
1450 sc.CheckSig(mid, _retsig, true); \
1451 sc.CheckStaticMethod(c, mid); \
1452 _retdecl; \
1453 _retasgn(baseEnv(env)->CallStatic##_jname##MethodV(env, c, mid, args)); \
1454 _retok; \
1455 } \
1456 static _ctype CallStatic##_jname##MethodA(JNIEnv* env, jclass c, jmethodID mid, jvalue* args) \
1457 { \
1458 CHECK_JNI_ENTRY(kFlag_Default, "Ecm.", env, c, mid); /* TODO: args! */ \
1459 sc.CheckSig(mid, _retsig, true); \
1460 sc.CheckStaticMethod(c, mid); \
1461 _retdecl; \
1462 _retasgn(baseEnv(env)->CallStatic##_jname##MethodA(env, c, mid, args)); \
1463 _retok; \
1464 }
1465
1466 #define NON_VOID_RETURN(_retsig, _ctype) return CHECK_JNI_EXIT(_retsig, (_ctype) result)
1467 #define VOID_RETURN CHECK_JNI_EXIT_VOID()
1468
1469 CALL(jobject, Object, mirror::Object* result, result = reinterpret_cast<mirror::Object*>, NON_VOID_RETURN("L", jobject), "L");
1470 CALL(jboolean, Boolean, jboolean result, result =, NON_VOID_RETURN("Z", jboolean), "Z");
1471 CALL(jbyte, Byte, jbyte result, result =, NON_VOID_RETURN("B", jbyte), "B");
1472 CALL(jchar, Char, jchar result, result =, NON_VOID_RETURN("C", jchar), "C");
1473 CALL(jshort, Short, jshort result, result =, NON_VOID_RETURN("S", jshort), "S");
1474 CALL(jint, Int, jint result, result =, NON_VOID_RETURN("I", jint), "I");
1475 CALL(jlong, Long, jlong result, result =, NON_VOID_RETURN("J", jlong), "J");
1476 CALL(jfloat, Float, jfloat result, result =, NON_VOID_RETURN("F", jfloat), "F");
1477 CALL(jdouble, Double, jdouble result, result =, NON_VOID_RETURN("D", jdouble), "D");
1478 CALL(void, Void, , , VOID_RETURN, "V");
1479
NewString(JNIEnv * env,const jchar * unicodeChars,jsize len)1480 static jstring NewString(JNIEnv* env, const jchar* unicodeChars, jsize len) {
1481 CHECK_JNI_ENTRY(kFlag_Default, "Epz", env, unicodeChars, len);
1482 return CHECK_JNI_EXIT("s", baseEnv(env)->NewString(env, unicodeChars, len));
1483 }
1484
GetStringLength(JNIEnv * env,jstring string)1485 static jsize GetStringLength(JNIEnv* env, jstring string) {
1486 CHECK_JNI_ENTRY(kFlag_CritOkay, "Es", env, string);
1487 return CHECK_JNI_EXIT("I", baseEnv(env)->GetStringLength(env, string));
1488 }
1489
GetStringChars(JNIEnv * env,jstring java_string,jboolean * isCopy)1490 static const jchar* GetStringChars(JNIEnv* env, jstring java_string, jboolean* isCopy) {
1491 CHECK_JNI_ENTRY(kFlag_CritOkay, "Esp", env, java_string, isCopy);
1492 const jchar* result = baseEnv(env)->GetStringChars(env, java_string, isCopy);
1493 if (sc.ForceCopy() && result != nullptr) {
1494 mirror::String* s = sc.soa().Decode<mirror::String*>(java_string);
1495 int byteCount = s->GetLength() * 2;
1496 result = (const jchar*) GuardedCopy::Create(result, byteCount, false);
1497 if (isCopy != nullptr) {
1498 *isCopy = JNI_TRUE;
1499 }
1500 }
1501 return CHECK_JNI_EXIT("p", result);
1502 }
1503
ReleaseStringChars(JNIEnv * env,jstring string,const jchar * chars)1504 static void ReleaseStringChars(JNIEnv* env, jstring string, const jchar* chars) {
1505 CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "Esp", env, string, chars);
1506 sc.CheckNonNull(chars);
1507 if (sc.ForceCopy()) {
1508 GuardedCopy::Check(__FUNCTION__, chars, false);
1509 chars = reinterpret_cast<const jchar*>(GuardedCopy::Destroy(const_cast<jchar*>(chars)));
1510 }
1511 baseEnv(env)->ReleaseStringChars(env, string, chars);
1512 CHECK_JNI_EXIT_VOID();
1513 }
1514
NewStringUTF(JNIEnv * env,const char * bytes)1515 static jstring NewStringUTF(JNIEnv* env, const char* bytes) {
1516 CHECK_JNI_ENTRY(kFlag_NullableUtf, "Eu", env, bytes); // TODO: show pointer and truncate string.
1517 return CHECK_JNI_EXIT("s", baseEnv(env)->NewStringUTF(env, bytes));
1518 }
1519
GetStringUTFLength(JNIEnv * env,jstring string)1520 static jsize GetStringUTFLength(JNIEnv* env, jstring string) {
1521 CHECK_JNI_ENTRY(kFlag_CritOkay, "Es", env, string);
1522 return CHECK_JNI_EXIT("I", baseEnv(env)->GetStringUTFLength(env, string));
1523 }
1524
GetStringUTFChars(JNIEnv * env,jstring string,jboolean * isCopy)1525 static const char* GetStringUTFChars(JNIEnv* env, jstring string, jboolean* isCopy) {
1526 CHECK_JNI_ENTRY(kFlag_CritOkay, "Esp", env, string, isCopy);
1527 const char* result = baseEnv(env)->GetStringUTFChars(env, string, isCopy);
1528 if (sc.ForceCopy() && result != nullptr) {
1529 result = (const char*) GuardedCopy::Create(result, strlen(result) + 1, false);
1530 if (isCopy != nullptr) {
1531 *isCopy = JNI_TRUE;
1532 }
1533 }
1534 return CHECK_JNI_EXIT("u", result); // TODO: show pointer and truncate string.
1535 }
1536
ReleaseStringUTFChars(JNIEnv * env,jstring string,const char * utf)1537 static void ReleaseStringUTFChars(JNIEnv* env, jstring string, const char* utf) {
1538 CHECK_JNI_ENTRY(kFlag_ExcepOkay | kFlag_Release, "Esu", env, string, utf); // TODO: show pointer and truncate string.
1539 if (sc.ForceCopy()) {
1540 GuardedCopy::Check(__FUNCTION__, utf, false);
1541 utf = reinterpret_cast<const char*>(GuardedCopy::Destroy(const_cast<char*>(utf)));
1542 }
1543 baseEnv(env)->ReleaseStringUTFChars(env, string, utf);
1544 CHECK_JNI_EXIT_VOID();
1545 }
1546
GetArrayLength(JNIEnv * env,jarray array)1547 static jsize GetArrayLength(JNIEnv* env, jarray array) {
1548 CHECK_JNI_ENTRY(kFlag_CritOkay, "Ea", env, array);
1549 return CHECK_JNI_EXIT("I", baseEnv(env)->GetArrayLength(env, array));
1550 }
1551
NewObjectArray(JNIEnv * env,jsize length,jclass elementClass,jobject initialElement)1552 static jobjectArray NewObjectArray(JNIEnv* env, jsize length, jclass elementClass, jobject initialElement) {
1553 CHECK_JNI_ENTRY(kFlag_Default, "EzcL", env, length, elementClass, initialElement);
1554 return CHECK_JNI_EXIT("a", baseEnv(env)->NewObjectArray(env, length, elementClass, initialElement));
1555 }
1556
GetObjectArrayElement(JNIEnv * env,jobjectArray array,jsize index)1557 static jobject GetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index) {
1558 CHECK_JNI_ENTRY(kFlag_Default, "EaI", env, array, index);
1559 return CHECK_JNI_EXIT("L", baseEnv(env)->GetObjectArrayElement(env, array, index));
1560 }
1561
SetObjectArrayElement(JNIEnv * env,jobjectArray array,jsize index,jobject value)1562 static void SetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index, jobject value) {
1563 CHECK_JNI_ENTRY(kFlag_Default, "EaIL", env, array, index, value);
1564 baseEnv(env)->SetObjectArrayElement(env, array, index, value);
1565 CHECK_JNI_EXIT_VOID();
1566 }
1567
1568 #define NEW_PRIMITIVE_ARRAY(_artype, _jname) \
1569 static _artype New##_jname##Array(JNIEnv* env, jsize length) { \
1570 CHECK_JNI_ENTRY(kFlag_Default, "Ez", env, length); \
1571 return CHECK_JNI_EXIT("a", baseEnv(env)->New##_jname##Array(env, length)); \
1572 }
1573 NEW_PRIMITIVE_ARRAY(jbooleanArray, Boolean);
1574 NEW_PRIMITIVE_ARRAY(jbyteArray, Byte);
1575 NEW_PRIMITIVE_ARRAY(jcharArray, Char);
1576 NEW_PRIMITIVE_ARRAY(jshortArray, Short);
1577 NEW_PRIMITIVE_ARRAY(jintArray, Int);
1578 NEW_PRIMITIVE_ARRAY(jlongArray, Long);
1579 NEW_PRIMITIVE_ARRAY(jfloatArray, Float);
1580 NEW_PRIMITIVE_ARRAY(jdoubleArray, Double);
1581
1582 struct ForceCopyGetChecker {
1583 public:
ForceCopyGetCheckerart::CheckJNI::ForceCopyGetChecker1584 ForceCopyGetChecker(ScopedCheck& sc, jboolean* isCopy) {
1585 force_copy = sc.ForceCopy();
1586 no_copy = 0;
1587 if (force_copy && isCopy != nullptr) {
1588 // Capture this before the base call tramples on it.
1589 no_copy = *reinterpret_cast<uint32_t*>(isCopy);
1590 }
1591 }
1592
1593 template<typename ResultT>
Checkart::CheckJNI::ForceCopyGetChecker1594 ResultT Check(JNIEnv* env, jarray array, jboolean* isCopy, ResultT result) {
1595 if (force_copy && result != nullptr) {
1596 result = reinterpret_cast<ResultT>(CreateGuardedPACopy(env, array, isCopy));
1597 }
1598 return result;
1599 }
1600
1601 uint32_t no_copy;
1602 bool force_copy;
1603 };
1604
1605 #define GET_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname) \
1606 static _ctype* Get##_jname##ArrayElements(JNIEnv* env, _ctype##Array array, jboolean* isCopy) { \
1607 CHECK_JNI_ENTRY(kFlag_Default, "Eap", env, array, isCopy); \
1608 _ctype* result = ForceCopyGetChecker(sc, isCopy).Check(env, array, isCopy, baseEnv(env)->Get##_jname##ArrayElements(env, array, isCopy)); \
1609 return CHECK_JNI_EXIT("p", result); \
1610 }
1611
1612 #define RELEASE_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname) \
1613 static void Release##_jname##ArrayElements(JNIEnv* env, _ctype##Array array, _ctype* elems, jint mode) { \
1614 CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "Eapr", env, array, elems, mode); \
1615 sc.CheckNonNull(elems); \
1616 if (sc.ForceCopy()) { \
1617 ReleaseGuardedPACopy(env, array, elems, mode); \
1618 } \
1619 baseEnv(env)->Release##_jname##ArrayElements(env, array, elems, mode); \
1620 CHECK_JNI_EXIT_VOID(); \
1621 }
1622
1623 #define GET_PRIMITIVE_ARRAY_REGION(_ctype, _jname) \
1624 static void Get##_jname##ArrayRegion(JNIEnv* env, _ctype##Array array, jsize start, jsize len, _ctype* buf) { \
1625 CHECK_JNI_ENTRY(kFlag_Default, "EaIIp", env, array, start, len, buf); \
1626 baseEnv(env)->Get##_jname##ArrayRegion(env, array, start, len, buf); \
1627 CHECK_JNI_EXIT_VOID(); \
1628 }
1629
1630 #define SET_PRIMITIVE_ARRAY_REGION(_ctype, _jname) \
1631 static void Set##_jname##ArrayRegion(JNIEnv* env, _ctype##Array array, jsize start, jsize len, const _ctype* buf) { \
1632 CHECK_JNI_ENTRY(kFlag_Default, "EaIIp", env, array, start, len, buf); \
1633 baseEnv(env)->Set##_jname##ArrayRegion(env, array, start, len, buf); \
1634 CHECK_JNI_EXIT_VOID(); \
1635 }
1636
1637 #define PRIMITIVE_ARRAY_FUNCTIONS(_ctype, _jname, _typechar) \
1638 GET_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname); \
1639 RELEASE_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname); \
1640 GET_PRIMITIVE_ARRAY_REGION(_ctype, _jname); \
1641 SET_PRIMITIVE_ARRAY_REGION(_ctype, _jname);
1642
1643 // TODO: verify primitive array type matches call type.
1644 PRIMITIVE_ARRAY_FUNCTIONS(jboolean, Boolean, 'Z');
1645 PRIMITIVE_ARRAY_FUNCTIONS(jbyte, Byte, 'B');
1646 PRIMITIVE_ARRAY_FUNCTIONS(jchar, Char, 'C');
1647 PRIMITIVE_ARRAY_FUNCTIONS(jshort, Short, 'S');
1648 PRIMITIVE_ARRAY_FUNCTIONS(jint, Int, 'I');
1649 PRIMITIVE_ARRAY_FUNCTIONS(jlong, Long, 'J');
1650 PRIMITIVE_ARRAY_FUNCTIONS(jfloat, Float, 'F');
1651 PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, 'D');
1652
RegisterNatives(JNIEnv * env,jclass c,const JNINativeMethod * methods,jint nMethods)1653 static jint RegisterNatives(JNIEnv* env, jclass c, const JNINativeMethod* methods, jint nMethods) {
1654 CHECK_JNI_ENTRY(kFlag_Default, "EcpI", env, c, methods, nMethods);
1655 return CHECK_JNI_EXIT("I", baseEnv(env)->RegisterNatives(env, c, methods, nMethods));
1656 }
1657
UnregisterNatives(JNIEnv * env,jclass c)1658 static jint UnregisterNatives(JNIEnv* env, jclass c) {
1659 CHECK_JNI_ENTRY(kFlag_Default, "Ec", env, c);
1660 return CHECK_JNI_EXIT("I", baseEnv(env)->UnregisterNatives(env, c));
1661 }
1662
MonitorEnter(JNIEnv * env,jobject obj)1663 static jint MonitorEnter(JNIEnv* env, jobject obj) {
1664 CHECK_JNI_ENTRY(kFlag_Default, "EL", env, obj);
1665 if (!sc.CheckInstance(ScopedCheck::kObject, obj)) {
1666 return JNI_ERR; // Only for jni_internal_test. Real code will have aborted already.
1667 }
1668 return CHECK_JNI_EXIT("I", baseEnv(env)->MonitorEnter(env, obj));
1669 }
1670
MonitorExit(JNIEnv * env,jobject obj)1671 static jint MonitorExit(JNIEnv* env, jobject obj) {
1672 CHECK_JNI_ENTRY(kFlag_Default | kFlag_ExcepOkay, "EL", env, obj);
1673 if (!sc.CheckInstance(ScopedCheck::kObject, obj)) {
1674 return JNI_ERR; // Only for jni_internal_test. Real code will have aborted already.
1675 }
1676 return CHECK_JNI_EXIT("I", baseEnv(env)->MonitorExit(env, obj));
1677 }
1678
GetJavaVM(JNIEnv * env,JavaVM ** vm)1679 static jint GetJavaVM(JNIEnv *env, JavaVM **vm) {
1680 CHECK_JNI_ENTRY(kFlag_Default, "Ep", env, vm);
1681 return CHECK_JNI_EXIT("I", baseEnv(env)->GetJavaVM(env, vm));
1682 }
1683
GetStringRegion(JNIEnv * env,jstring str,jsize start,jsize len,jchar * buf)1684 static void GetStringRegion(JNIEnv* env, jstring str, jsize start, jsize len, jchar* buf) {
1685 CHECK_JNI_ENTRY(kFlag_CritOkay, "EsIIp", env, str, start, len, buf);
1686 baseEnv(env)->GetStringRegion(env, str, start, len, buf);
1687 CHECK_JNI_EXIT_VOID();
1688 }
1689
GetStringUTFRegion(JNIEnv * env,jstring str,jsize start,jsize len,char * buf)1690 static void GetStringUTFRegion(JNIEnv* env, jstring str, jsize start, jsize len, char* buf) {
1691 CHECK_JNI_ENTRY(kFlag_CritOkay, "EsIIp", env, str, start, len, buf);
1692 baseEnv(env)->GetStringUTFRegion(env, str, start, len, buf);
1693 CHECK_JNI_EXIT_VOID();
1694 }
1695
GetPrimitiveArrayCritical(JNIEnv * env,jarray array,jboolean * isCopy)1696 static void* GetPrimitiveArrayCritical(JNIEnv* env, jarray array, jboolean* isCopy) {
1697 CHECK_JNI_ENTRY(kFlag_CritGet, "Eap", env, array, isCopy);
1698 void* result = baseEnv(env)->GetPrimitiveArrayCritical(env, array, isCopy);
1699 if (sc.ForceCopy() && result != nullptr) {
1700 result = CreateGuardedPACopy(env, array, isCopy);
1701 }
1702 return CHECK_JNI_EXIT("p", result);
1703 }
1704
ReleasePrimitiveArrayCritical(JNIEnv * env,jarray array,void * carray,jint mode)1705 static void ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array, void* carray, jint mode) {
1706 CHECK_JNI_ENTRY(kFlag_CritRelease | kFlag_ExcepOkay, "Eapr", env, array, carray, mode);
1707 sc.CheckNonNull(carray);
1708 if (sc.ForceCopy()) {
1709 ReleaseGuardedPACopy(env, array, carray, mode);
1710 }
1711 baseEnv(env)->ReleasePrimitiveArrayCritical(env, array, carray, mode);
1712 CHECK_JNI_EXIT_VOID();
1713 }
1714
GetStringCritical(JNIEnv * env,jstring java_string,jboolean * isCopy)1715 static const jchar* GetStringCritical(JNIEnv* env, jstring java_string, jboolean* isCopy) {
1716 CHECK_JNI_ENTRY(kFlag_CritGet, "Esp", env, java_string, isCopy);
1717 const jchar* result = baseEnv(env)->GetStringCritical(env, java_string, isCopy);
1718 if (sc.ForceCopy() && result != nullptr) {
1719 mirror::String* s = sc.soa().Decode<mirror::String*>(java_string);
1720 int byteCount = s->GetLength() * 2;
1721 result = (const jchar*) GuardedCopy::Create(result, byteCount, false);
1722 if (isCopy != nullptr) {
1723 *isCopy = JNI_TRUE;
1724 }
1725 }
1726 return CHECK_JNI_EXIT("p", result);
1727 }
1728
ReleaseStringCritical(JNIEnv * env,jstring string,const jchar * carray)1729 static void ReleaseStringCritical(JNIEnv* env, jstring string, const jchar* carray) {
1730 CHECK_JNI_ENTRY(kFlag_CritRelease | kFlag_ExcepOkay, "Esp", env, string, carray);
1731 sc.CheckNonNull(carray);
1732 if (sc.ForceCopy()) {
1733 GuardedCopy::Check(__FUNCTION__, carray, false);
1734 carray = reinterpret_cast<const jchar*>(GuardedCopy::Destroy(const_cast<jchar*>(carray)));
1735 }
1736 baseEnv(env)->ReleaseStringCritical(env, string, carray);
1737 CHECK_JNI_EXIT_VOID();
1738 }
1739
NewWeakGlobalRef(JNIEnv * env,jobject obj)1740 static jweak NewWeakGlobalRef(JNIEnv* env, jobject obj) {
1741 CHECK_JNI_ENTRY(kFlag_Default, "EL", env, obj);
1742 return CHECK_JNI_EXIT("L", baseEnv(env)->NewWeakGlobalRef(env, obj));
1743 }
1744
ExceptionCheck(JNIEnv * env)1745 static jboolean ExceptionCheck(JNIEnv* env) {
1746 CHECK_JNI_ENTRY(kFlag_CritOkay | kFlag_ExcepOkay, "E", env);
1747 return CHECK_JNI_EXIT("b", baseEnv(env)->ExceptionCheck(env));
1748 }
1749
GetObjectRefType(JNIEnv * env,jobject obj)1750 static jobjectRefType GetObjectRefType(JNIEnv* env, jobject obj) {
1751 // Note: we use "Ep" rather than "EL" because this is the one JNI function
1752 // that it's okay to pass an invalid reference to.
1753 CHECK_JNI_ENTRY(kFlag_Default, "Ep", env, obj);
1754 // TODO: proper decoding of jobjectRefType!
1755 return CHECK_JNI_EXIT("I", baseEnv(env)->GetObjectRefType(env, obj));
1756 }
1757
NewDirectByteBuffer(JNIEnv * env,void * address,jlong capacity)1758 static jobject NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity) {
1759 CHECK_JNI_ENTRY(kFlag_Default, "EpJ", env, address, capacity);
1760 if (address == nullptr) {
1761 JniAbortF(__FUNCTION__, "non-nullable address is NULL");
1762 return nullptr;
1763 }
1764 return CHECK_JNI_EXIT("L", baseEnv(env)->NewDirectByteBuffer(env, address, capacity));
1765 }
1766
GetDirectBufferAddress(JNIEnv * env,jobject buf)1767 static void* GetDirectBufferAddress(JNIEnv* env, jobject buf) {
1768 CHECK_JNI_ENTRY(kFlag_Default, "EL", env, buf);
1769 // TODO: check that 'buf' is a java.nio.Buffer.
1770 return CHECK_JNI_EXIT("p", baseEnv(env)->GetDirectBufferAddress(env, buf));
1771 }
1772
GetDirectBufferCapacity(JNIEnv * env,jobject buf)1773 static jlong GetDirectBufferCapacity(JNIEnv* env, jobject buf) {
1774 CHECK_JNI_ENTRY(kFlag_Default, "EL", env, buf);
1775 // TODO: check that 'buf' is a java.nio.Buffer.
1776 return CHECK_JNI_EXIT("J", baseEnv(env)->GetDirectBufferCapacity(env, buf));
1777 }
1778
1779 private:
baseEnv(JNIEnv * env)1780 static inline const JNINativeInterface* baseEnv(JNIEnv* env) {
1781 return reinterpret_cast<JNIEnvExt*>(env)->unchecked_functions;
1782 }
1783 };
1784
1785 const JNINativeInterface gCheckNativeInterface = {
1786 nullptr, // reserved0.
1787 nullptr, // reserved1.
1788 nullptr, // reserved2.
1789 nullptr, // reserved3.
1790 CheckJNI::GetVersion,
1791 CheckJNI::DefineClass,
1792 CheckJNI::FindClass,
1793 CheckJNI::FromReflectedMethod,
1794 CheckJNI::FromReflectedField,
1795 CheckJNI::ToReflectedMethod,
1796 CheckJNI::GetSuperclass,
1797 CheckJNI::IsAssignableFrom,
1798 CheckJNI::ToReflectedField,
1799 CheckJNI::Throw,
1800 CheckJNI::ThrowNew,
1801 CheckJNI::ExceptionOccurred,
1802 CheckJNI::ExceptionDescribe,
1803 CheckJNI::ExceptionClear,
1804 CheckJNI::FatalError,
1805 CheckJNI::PushLocalFrame,
1806 CheckJNI::PopLocalFrame,
1807 CheckJNI::NewGlobalRef,
1808 CheckJNI::DeleteGlobalRef,
1809 CheckJNI::DeleteLocalRef,
1810 CheckJNI::IsSameObject,
1811 CheckJNI::NewLocalRef,
1812 CheckJNI::EnsureLocalCapacity,
1813 CheckJNI::AllocObject,
1814 CheckJNI::NewObject,
1815 CheckJNI::NewObjectV,
1816 CheckJNI::NewObjectA,
1817 CheckJNI::GetObjectClass,
1818 CheckJNI::IsInstanceOf,
1819 CheckJNI::GetMethodID,
1820 CheckJNI::CallObjectMethod,
1821 CheckJNI::CallObjectMethodV,
1822 CheckJNI::CallObjectMethodA,
1823 CheckJNI::CallBooleanMethod,
1824 CheckJNI::CallBooleanMethodV,
1825 CheckJNI::CallBooleanMethodA,
1826 CheckJNI::CallByteMethod,
1827 CheckJNI::CallByteMethodV,
1828 CheckJNI::CallByteMethodA,
1829 CheckJNI::CallCharMethod,
1830 CheckJNI::CallCharMethodV,
1831 CheckJNI::CallCharMethodA,
1832 CheckJNI::CallShortMethod,
1833 CheckJNI::CallShortMethodV,
1834 CheckJNI::CallShortMethodA,
1835 CheckJNI::CallIntMethod,
1836 CheckJNI::CallIntMethodV,
1837 CheckJNI::CallIntMethodA,
1838 CheckJNI::CallLongMethod,
1839 CheckJNI::CallLongMethodV,
1840 CheckJNI::CallLongMethodA,
1841 CheckJNI::CallFloatMethod,
1842 CheckJNI::CallFloatMethodV,
1843 CheckJNI::CallFloatMethodA,
1844 CheckJNI::CallDoubleMethod,
1845 CheckJNI::CallDoubleMethodV,
1846 CheckJNI::CallDoubleMethodA,
1847 CheckJNI::CallVoidMethod,
1848 CheckJNI::CallVoidMethodV,
1849 CheckJNI::CallVoidMethodA,
1850 CheckJNI::CallNonvirtualObjectMethod,
1851 CheckJNI::CallNonvirtualObjectMethodV,
1852 CheckJNI::CallNonvirtualObjectMethodA,
1853 CheckJNI::CallNonvirtualBooleanMethod,
1854 CheckJNI::CallNonvirtualBooleanMethodV,
1855 CheckJNI::CallNonvirtualBooleanMethodA,
1856 CheckJNI::CallNonvirtualByteMethod,
1857 CheckJNI::CallNonvirtualByteMethodV,
1858 CheckJNI::CallNonvirtualByteMethodA,
1859 CheckJNI::CallNonvirtualCharMethod,
1860 CheckJNI::CallNonvirtualCharMethodV,
1861 CheckJNI::CallNonvirtualCharMethodA,
1862 CheckJNI::CallNonvirtualShortMethod,
1863 CheckJNI::CallNonvirtualShortMethodV,
1864 CheckJNI::CallNonvirtualShortMethodA,
1865 CheckJNI::CallNonvirtualIntMethod,
1866 CheckJNI::CallNonvirtualIntMethodV,
1867 CheckJNI::CallNonvirtualIntMethodA,
1868 CheckJNI::CallNonvirtualLongMethod,
1869 CheckJNI::CallNonvirtualLongMethodV,
1870 CheckJNI::CallNonvirtualLongMethodA,
1871 CheckJNI::CallNonvirtualFloatMethod,
1872 CheckJNI::CallNonvirtualFloatMethodV,
1873 CheckJNI::CallNonvirtualFloatMethodA,
1874 CheckJNI::CallNonvirtualDoubleMethod,
1875 CheckJNI::CallNonvirtualDoubleMethodV,
1876 CheckJNI::CallNonvirtualDoubleMethodA,
1877 CheckJNI::CallNonvirtualVoidMethod,
1878 CheckJNI::CallNonvirtualVoidMethodV,
1879 CheckJNI::CallNonvirtualVoidMethodA,
1880 CheckJNI::GetFieldID,
1881 CheckJNI::GetObjectField,
1882 CheckJNI::GetBooleanField,
1883 CheckJNI::GetByteField,
1884 CheckJNI::GetCharField,
1885 CheckJNI::GetShortField,
1886 CheckJNI::GetIntField,
1887 CheckJNI::GetLongField,
1888 CheckJNI::GetFloatField,
1889 CheckJNI::GetDoubleField,
1890 CheckJNI::SetObjectField,
1891 CheckJNI::SetBooleanField,
1892 CheckJNI::SetByteField,
1893 CheckJNI::SetCharField,
1894 CheckJNI::SetShortField,
1895 CheckJNI::SetIntField,
1896 CheckJNI::SetLongField,
1897 CheckJNI::SetFloatField,
1898 CheckJNI::SetDoubleField,
1899 CheckJNI::GetStaticMethodID,
1900 CheckJNI::CallStaticObjectMethod,
1901 CheckJNI::CallStaticObjectMethodV,
1902 CheckJNI::CallStaticObjectMethodA,
1903 CheckJNI::CallStaticBooleanMethod,
1904 CheckJNI::CallStaticBooleanMethodV,
1905 CheckJNI::CallStaticBooleanMethodA,
1906 CheckJNI::CallStaticByteMethod,
1907 CheckJNI::CallStaticByteMethodV,
1908 CheckJNI::CallStaticByteMethodA,
1909 CheckJNI::CallStaticCharMethod,
1910 CheckJNI::CallStaticCharMethodV,
1911 CheckJNI::CallStaticCharMethodA,
1912 CheckJNI::CallStaticShortMethod,
1913 CheckJNI::CallStaticShortMethodV,
1914 CheckJNI::CallStaticShortMethodA,
1915 CheckJNI::CallStaticIntMethod,
1916 CheckJNI::CallStaticIntMethodV,
1917 CheckJNI::CallStaticIntMethodA,
1918 CheckJNI::CallStaticLongMethod,
1919 CheckJNI::CallStaticLongMethodV,
1920 CheckJNI::CallStaticLongMethodA,
1921 CheckJNI::CallStaticFloatMethod,
1922 CheckJNI::CallStaticFloatMethodV,
1923 CheckJNI::CallStaticFloatMethodA,
1924 CheckJNI::CallStaticDoubleMethod,
1925 CheckJNI::CallStaticDoubleMethodV,
1926 CheckJNI::CallStaticDoubleMethodA,
1927 CheckJNI::CallStaticVoidMethod,
1928 CheckJNI::CallStaticVoidMethodV,
1929 CheckJNI::CallStaticVoidMethodA,
1930 CheckJNI::GetStaticFieldID,
1931 CheckJNI::GetStaticObjectField,
1932 CheckJNI::GetStaticBooleanField,
1933 CheckJNI::GetStaticByteField,
1934 CheckJNI::GetStaticCharField,
1935 CheckJNI::GetStaticShortField,
1936 CheckJNI::GetStaticIntField,
1937 CheckJNI::GetStaticLongField,
1938 CheckJNI::GetStaticFloatField,
1939 CheckJNI::GetStaticDoubleField,
1940 CheckJNI::SetStaticObjectField,
1941 CheckJNI::SetStaticBooleanField,
1942 CheckJNI::SetStaticByteField,
1943 CheckJNI::SetStaticCharField,
1944 CheckJNI::SetStaticShortField,
1945 CheckJNI::SetStaticIntField,
1946 CheckJNI::SetStaticLongField,
1947 CheckJNI::SetStaticFloatField,
1948 CheckJNI::SetStaticDoubleField,
1949 CheckJNI::NewString,
1950 CheckJNI::GetStringLength,
1951 CheckJNI::GetStringChars,
1952 CheckJNI::ReleaseStringChars,
1953 CheckJNI::NewStringUTF,
1954 CheckJNI::GetStringUTFLength,
1955 CheckJNI::GetStringUTFChars,
1956 CheckJNI::ReleaseStringUTFChars,
1957 CheckJNI::GetArrayLength,
1958 CheckJNI::NewObjectArray,
1959 CheckJNI::GetObjectArrayElement,
1960 CheckJNI::SetObjectArrayElement,
1961 CheckJNI::NewBooleanArray,
1962 CheckJNI::NewByteArray,
1963 CheckJNI::NewCharArray,
1964 CheckJNI::NewShortArray,
1965 CheckJNI::NewIntArray,
1966 CheckJNI::NewLongArray,
1967 CheckJNI::NewFloatArray,
1968 CheckJNI::NewDoubleArray,
1969 CheckJNI::GetBooleanArrayElements,
1970 CheckJNI::GetByteArrayElements,
1971 CheckJNI::GetCharArrayElements,
1972 CheckJNI::GetShortArrayElements,
1973 CheckJNI::GetIntArrayElements,
1974 CheckJNI::GetLongArrayElements,
1975 CheckJNI::GetFloatArrayElements,
1976 CheckJNI::GetDoubleArrayElements,
1977 CheckJNI::ReleaseBooleanArrayElements,
1978 CheckJNI::ReleaseByteArrayElements,
1979 CheckJNI::ReleaseCharArrayElements,
1980 CheckJNI::ReleaseShortArrayElements,
1981 CheckJNI::ReleaseIntArrayElements,
1982 CheckJNI::ReleaseLongArrayElements,
1983 CheckJNI::ReleaseFloatArrayElements,
1984 CheckJNI::ReleaseDoubleArrayElements,
1985 CheckJNI::GetBooleanArrayRegion,
1986 CheckJNI::GetByteArrayRegion,
1987 CheckJNI::GetCharArrayRegion,
1988 CheckJNI::GetShortArrayRegion,
1989 CheckJNI::GetIntArrayRegion,
1990 CheckJNI::GetLongArrayRegion,
1991 CheckJNI::GetFloatArrayRegion,
1992 CheckJNI::GetDoubleArrayRegion,
1993 CheckJNI::SetBooleanArrayRegion,
1994 CheckJNI::SetByteArrayRegion,
1995 CheckJNI::SetCharArrayRegion,
1996 CheckJNI::SetShortArrayRegion,
1997 CheckJNI::SetIntArrayRegion,
1998 CheckJNI::SetLongArrayRegion,
1999 CheckJNI::SetFloatArrayRegion,
2000 CheckJNI::SetDoubleArrayRegion,
2001 CheckJNI::RegisterNatives,
2002 CheckJNI::UnregisterNatives,
2003 CheckJNI::MonitorEnter,
2004 CheckJNI::MonitorExit,
2005 CheckJNI::GetJavaVM,
2006 CheckJNI::GetStringRegion,
2007 CheckJNI::GetStringUTFRegion,
2008 CheckJNI::GetPrimitiveArrayCritical,
2009 CheckJNI::ReleasePrimitiveArrayCritical,
2010 CheckJNI::GetStringCritical,
2011 CheckJNI::ReleaseStringCritical,
2012 CheckJNI::NewWeakGlobalRef,
2013 CheckJNI::DeleteWeakGlobalRef,
2014 CheckJNI::ExceptionCheck,
2015 CheckJNI::NewDirectByteBuffer,
2016 CheckJNI::GetDirectBufferAddress,
2017 CheckJNI::GetDirectBufferCapacity,
2018 CheckJNI::GetObjectRefType,
2019 };
2020
GetCheckJniNativeInterface()2021 const JNINativeInterface* GetCheckJniNativeInterface() {
2022 return &gCheckNativeInterface;
2023 }
2024
2025 class CheckJII {
2026 public:
DestroyJavaVM(JavaVM * vm)2027 static jint DestroyJavaVM(JavaVM* vm) {
2028 ScopedCheck sc(vm, false, __FUNCTION__);
2029 sc.Check(true, "v", vm);
2030 return CHECK_JNI_EXIT("I", BaseVm(vm)->DestroyJavaVM(vm));
2031 }
2032
AttachCurrentThread(JavaVM * vm,JNIEnv ** p_env,void * thr_args)2033 static jint AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
2034 ScopedCheck sc(vm, false, __FUNCTION__);
2035 sc.Check(true, "vpp", vm, p_env, thr_args);
2036 return CHECK_JNI_EXIT("I", BaseVm(vm)->AttachCurrentThread(vm, p_env, thr_args));
2037 }
2038
AttachCurrentThreadAsDaemon(JavaVM * vm,JNIEnv ** p_env,void * thr_args)2039 static jint AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
2040 ScopedCheck sc(vm, false, __FUNCTION__);
2041 sc.Check(true, "vpp", vm, p_env, thr_args);
2042 return CHECK_JNI_EXIT("I", BaseVm(vm)->AttachCurrentThreadAsDaemon(vm, p_env, thr_args));
2043 }
2044
DetachCurrentThread(JavaVM * vm)2045 static jint DetachCurrentThread(JavaVM* vm) {
2046 ScopedCheck sc(vm, true, __FUNCTION__);
2047 sc.Check(true, "v", vm);
2048 return CHECK_JNI_EXIT("I", BaseVm(vm)->DetachCurrentThread(vm));
2049 }
2050
GetEnv(JavaVM * vm,void ** env,jint version)2051 static jint GetEnv(JavaVM* vm, void** env, jint version) {
2052 ScopedCheck sc(vm, true, __FUNCTION__);
2053 sc.Check(true, "vpI", vm);
2054 return CHECK_JNI_EXIT("I", BaseVm(vm)->GetEnv(vm, env, version));
2055 }
2056
2057 private:
BaseVm(JavaVM * vm)2058 static inline const JNIInvokeInterface* BaseVm(JavaVM* vm) {
2059 return reinterpret_cast<JavaVMExt*>(vm)->unchecked_functions;
2060 }
2061 };
2062
2063 const JNIInvokeInterface gCheckInvokeInterface = {
2064 nullptr, // reserved0
2065 nullptr, // reserved1
2066 nullptr, // reserved2
2067 CheckJII::DestroyJavaVM,
2068 CheckJII::AttachCurrentThread,
2069 CheckJII::DetachCurrentThread,
2070 CheckJII::GetEnv,
2071 CheckJII::AttachCurrentThreadAsDaemon
2072 };
2073
GetCheckJniInvokeInterface()2074 const JNIInvokeInterface* GetCheckJniInvokeInterface() {
2075 return &gCheckInvokeInterface;
2076 }
2077
2078 } // namespace art
2079