OSDN Git Service

Merge change 10482
[android-x86/dalvik.git] / vm / CheckJni.c
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 /*
18  * Support for -Xcheck:jni (the "careful" version of the JNI interfaces).
19  *
20  * We want to verify types, make sure class and field IDs are valid, and
21  * ensure that JNI's semantic expectations are being met.  JNI seems to
22  * be relatively lax when it comes to requirements for permission checks,
23  * e.g. access to private methods is generally allowed from anywhere.
24  *
25  * TODO: keep a counter on global Get/Release.  Report a warning if some Gets
26  * were not Released.  Do not count explicit Add/DeleteGlobalRef calls (or
27  * count them separately, so we can complain if they exceed a certain
28  * threshold).
29  *
30  * TODO: verify that the methodID passed into the Call functions is for
31  * a method in the specified class.
32  */
33 #include "Dalvik.h"
34 #include "JniInternal.h"
35
36 #include <zlib.h>
37
38 #define JNI_ENTER()     dvmChangeStatus(NULL, THREAD_RUNNING)
39 #define JNI_EXIT()      dvmChangeStatus(NULL, THREAD_NATIVE)
40
41 #define BASE_ENV(_env)  (((JNIEnvExt*)_env)->baseFuncTable)
42 #define BASE_VM(_vm)    (((JavaVMExt*)_vm)->baseFuncTable)
43
44 /*
45  * Flags passed into checkThread().
46  */
47 #define kFlag_Default       0x0000
48
49 #define kFlag_CritBad       0x0000      /* calling while in critical is bad */
50 #define kFlag_CritOkay      0x0001      /* ...okay */
51 #define kFlag_CritGet       0x0002      /* this is a critical "get" */
52 #define kFlag_CritRelease   0x0003      /* this is a critical "release" */
53 #define kFlag_CritMask      0x0003      /* bit mask to get "crit" value */
54
55 #define kFlag_ExcepBad      0x0000      /* raised exceptions are bad */
56 #define kFlag_ExcepOkay     0x0004      /* ...okay */
57
58 /*
59  * Enter/exit macros for JNI env "check" functions.  These do not change
60  * the thread state within the VM.
61  */
62 #define CHECK_ENTER(_env, _flags)                                           \
63     do {                                                                    \
64         JNI_TRACE(true, true);                                              \
65         checkThread(_env, _flags, __FUNCTION__);                            \
66     } while(false)
67
68 #define CHECK_EXIT(_env)                                                    \
69     do { JNI_TRACE(false, true); } while(false)
70
71
72 /*
73  * Enter/exit macros for JNI invocation interface "check" functions.  These
74  * do not change the thread state within the VM.
75  *
76  * Set "_hasmeth" to true if we have a valid thread with a method pointer.
77  * We won't have one before attaching a thread, after detaching a thread, or
78  * after destroying the VM.
79  */
80 #define CHECK_VMENTER(_vm, _hasmeth)                                        \
81     do { JNI_TRACE(true, _hasmeth); } while(false)
82 #define CHECK_VMEXIT(_vm, _hasmeth)                                         \
83     do { JNI_TRACE(false, _hasmeth); } while(false)
84
85 #define CHECK_FIELD_TYPE(_obj, _fieldid, _prim, _isstatic)                  \
86     checkFieldType(_obj, _fieldid, _prim, _isstatic, __FUNCTION__)
87 #define CHECK_CLASS(_env, _clazz)                                           \
88     checkClass(_env, _clazz, __FUNCTION__)
89 #define CHECK_STRING(_env, _str)                                            \
90     checkString(_env, _str, __FUNCTION__)
91 #define CHECK_UTF_STRING(_env, _str, _nullok)                               \
92     checkUtfString(_env, _str, _nullok, __FUNCTION__)
93 #define CHECK_CLASS_NAME(_env, _str)                                        \
94     checkClassName(_env, _str, __FUNCTION__)
95 #define CHECK_OBJECT(_env, _obj)                                            \
96     checkObject(_env, _obj, __FUNCTION__)
97 #define CHECK_ARRAY(_env, _array)                                           \
98     checkArray(_env, _array, __FUNCTION__)
99 #define CHECK_RELEASE_MODE(_env, _mode)                                     \
100     checkReleaseMode(_env, _mode, __FUNCTION__)
101 #define CHECK_LENGTH_POSITIVE(_env, _length)                                \
102     checkLengthPositive(_env, _length, __FUNCTION__)
103 #define CHECK_NON_NULL(_env, _ptr)                                          \
104     checkNonNull(_env, _ptr, __FUNCTION__)
105
106 #define CHECK_SIG(_env, _methid, _sigbyte, _isstatic)                       \
107     checkSig(_env, _methid, _sigbyte, _isstatic, __FUNCTION__)
108
109 /*
110  * Print trace message when both "checkJNI" and "verbose:jni" are enabled.
111  */
112 #define JNI_TRACE(_entry, _hasmeth)                                         \
113     do {                                                                    \
114         if (gDvm.verboseJni && (_entry)) {                                  \
115             static const char* classDescriptor = "???";                     \
116             static const char* methodName = "???";                          \
117             if (_hasmeth) {                                                 \
118                 const Method* meth = dvmGetCurrentJNIMethod();              \
119                 classDescriptor = meth->clazz->descriptor;                  \
120                 methodName = meth->name;                                    \
121             }                                                               \
122             /* use +6 to drop the leading "Check_" */                       \
123             LOGI("JNI: %s (from %s.%s)",                                    \
124                 (__FUNCTION__)+6, classDescriptor, methodName);             \
125         }                                                                   \
126     } while(false)
127
128 /*
129  * Log the current location.
130  *
131  * "func" looks like "Check_DeleteLocalRef"; we drop the "Check_".
132  */
133 static void showLocation(const Method* meth, const char* func)
134 {
135     char* desc = dexProtoCopyMethodDescriptor(&meth->prototype);
136     LOGW("             in %s.%s %s (%s)\n",
137         meth->clazz->descriptor, meth->name, desc, func + 6);
138     free(desc);
139 }
140
141 /*
142  * Abort if we are configured to bail out on JNI warnings.
143  */
144 static inline void abortMaybe()
145 {
146     JavaVMExt* vm = (JavaVMExt*) gDvm.vmList;
147     if (vm->warnError) {
148         dvmDumpThread(dvmThreadSelf(), false);
149         dvmAbort();
150     }
151 }
152
153 /*
154  * Verify that the current thread is (a) attached and (b) associated with
155  * this particular instance of JNIEnv.
156  *
157  * Verify that, if this thread previously made a critical "get" call, we
158  * do the corresponding "release" call before we try anything else.
159  *
160  * Verify that, if an exception has been raised, the native code doesn't
161  * make any JNI calls other than the Exception* methods.
162  *
163  * TODO? if we add support for non-JNI native calls, make sure that the
164  * method at the top of the interpreted stack is a JNI method call.  (Or
165  * set a flag in the Thread/JNIEnv when the call is made and clear it on
166  * return?)
167  *
168  * NOTE: we are still in THREAD_NATIVE mode.  A GC could happen at any time.
169  */
170 static void checkThread(JNIEnv* env, int flags, const char* func)
171 {
172     JNIEnvExt* threadEnv;
173     bool printWarn = false;
174     bool printException = false;
175
176     /* get the *correct* JNIEnv by going through our TLS pointer */
177     threadEnv = dvmGetJNIEnvForThread();
178
179     /*
180      * Verify that the JNIEnv we've been handed matches what we expected
181      * to receive.
182      */
183     if (threadEnv == NULL) {
184         LOGE("JNI ERROR: non-VM thread making JNI calls\n");
185         // don't set printWarn
186     } else if ((JNIEnvExt*) env != threadEnv) {
187         if (dvmThreadSelf()->threadId != threadEnv->envThreadId) {
188             LOGE("JNI: threadEnv != thread->env?\n");
189             dvmAbort();
190         }
191
192         LOGW("JNI WARNING: threadid=%d using env from threadid=%d\n",
193             threadEnv->envThreadId, ((JNIEnvExt*)env)->envThreadId);
194         printWarn = true;
195
196         /* this is a bad idea -- need to throw as we exit, or abort func */
197         //dvmThrowException("Ljava/lang/RuntimeException;",
198         //    "invalid use of JNI env ptr");
199     } else if (((JNIEnvExt*) env)->self != dvmThreadSelf()) {
200         /* correct JNIEnv*; make sure the "self" pointer is correct */
201         LOGE("JNI: env->self != thread-self\n");
202         dvmAbort();
203     }
204
205     /*
206      * Check for critical resource misuse.
207      */
208     switch (flags & kFlag_CritMask) {
209     case kFlag_CritOkay:    // okay to call this method
210         break;
211     case kFlag_CritBad:     // not okay to call
212         if (threadEnv->critical) {
213             LOGW("JNI WARNING: threadid=%d using JNI after critical get\n",
214                 threadEnv->envThreadId);
215             printWarn = true;
216         }
217         break;
218     case kFlag_CritGet:     // this is a "get" call
219         /* don't check here; we allow nested gets */
220         threadEnv->critical++;
221         break;
222     case kFlag_CritRelease: // this is a "release" call
223         threadEnv->critical--;
224         if (threadEnv->critical < 0) {
225             LOGW("JNI WARNING: threadid=%d called too many crit releases\n",
226                 threadEnv->envThreadId);
227             printWarn = true;
228         }
229         break;
230     default:
231         assert(false);
232     }
233
234     /*
235      * Check for raised exceptions.
236      */
237     if ((flags & kFlag_ExcepOkay) == 0 && dvmCheckException(dvmThreadSelf())) {
238         LOGW("JNI WARNING: JNI method called with exception raised\n");
239         printWarn = true;
240         printException = true;
241     }
242
243     if (false) {
244         Thread* self = dvmThreadSelf();
245         LOGW("NOW: %d\n",
246             (int) dvmReferenceTableEntries(&self->internalLocalRefTable));
247     }
248
249     if (printWarn)
250         showLocation(dvmGetCurrentJNIMethod(), func);
251     if (printException) {
252         LOGW("Pending exception is:\n");
253         dvmLogExceptionStackTrace();
254     }
255     if (printWarn)
256         abortMaybe();
257 }
258
259 /*
260  * Verify that the field is of the appropriate type.  If the field has an
261  * object type, "obj" is the object we're trying to assign into it.
262  *
263  * Works for both static and instance fields.
264  */
265 static void checkFieldType(jobject obj, jfieldID fieldID, PrimitiveType prim,
266     bool isStatic, const char* func)
267 {
268     static const char* primNameList[] = {
269         "Object/Array", "boolean", "char", "float", "double",
270         "byte", "short", "int", "long", "void"
271     };
272     const char** primNames = &primNameList[1];      // shift up for PRIM_NOT
273     Field* field = (Field*) fieldID;
274     bool printWarn = false;
275
276     if (fieldID == NULL) {
277         LOGE("JNI ERROR: null field ID\n");
278         abortMaybe();
279     }
280
281     if (field->signature[0] == 'L' || field->signature[0] == '[') {
282         if (obj != NULL) {
283             ClassObject* fieldClass =
284                 dvmFindLoadedClass(field->signature);
285             ClassObject* objClass = ((Object*)obj)->clazz;
286
287             assert(fieldClass != NULL);
288             assert(objClass != NULL);
289
290             if (!dvmInstanceof(objClass, fieldClass)) {
291                 LOGW("JNI WARNING: field '%s' with type '%s' set with wrong type (%s)\n",
292                     field->name, field->signature, objClass->descriptor);
293                 printWarn = true;
294             }
295         }
296     } else if (field->signature[0] != PRIM_TYPE_TO_LETTER[prim]) {
297         LOGW("JNI WARNING: field '%s' with type '%s' set with wrong type (%s)\n",
298             field->name, field->signature, primNames[prim]);
299         printWarn = true;
300     } else if (isStatic && !dvmIsStaticField(field)) {
301         if (isStatic)
302             LOGW("JNI WARNING: accessing non-static field %s as static\n",
303                 field->name);
304         else
305             LOGW("JNI WARNING: accessing static field %s as non-static\n",
306                 field->name);
307         printWarn = true;
308     }
309
310     if (printWarn) {
311         showLocation(dvmGetCurrentJNIMethod(), func);
312         abortMaybe();
313     }
314 }
315
316 /*
317  * Verify that "obj" is a valid object, and that it's an object that JNI
318  * is allowed to know about.  We allow NULL references.
319  *
320  * The caller should have switched to "running" mode before calling here.
321  */
322 static void checkObject(JNIEnv* env, jobject obj, const char* func)
323 {
324     UNUSED_PARAMETER(env);
325     bool printWarn = false;
326
327     if (obj == NULL)
328         return;
329     if (!dvmIsValidObject(obj)) {
330         LOGW("JNI WARNING: native code passing in bad object %p (%s)\n",
331             obj, func);
332         printWarn = true;
333     } else if (dvmGetJNIRefType(obj) == JNIInvalidRefType) {
334         LOGW("JNI WARNING: ref %p should not be visible to native code\n", obj);
335         printWarn = true;
336     }
337
338     if (printWarn) {
339         showLocation(dvmGetCurrentJNIMethod(), func);
340         abortMaybe();
341     }
342 }
343
344 /*
345  * Verify that "clazz" actually points to a class object.  (Also performs
346  * checkObject.)
347  *
348  * We probably don't need to identify where we're being called from,
349  * because the VM is most likely about to crash and leave a core dump
350  * if something is wrong.
351  *
352  * Because we're looking at an object on the GC heap, we have to switch
353  * to "running" mode before doing the checks.
354  */
355 static void checkClass(JNIEnv* env, jclass jclazz, const char* func)
356 {
357     JNI_ENTER();
358     bool printWarn = false;
359
360     ClassObject* clazz = (ClassObject*) jclazz;
361
362     if (clazz == NULL) {
363         LOGW("JNI WARNING: received null jclass\n");
364         printWarn = true;
365     } else if (!dvmIsValidObject((Object*) clazz)) {
366         LOGW("JNI WARNING: jclass points to invalid object %p\n", clazz);
367         printWarn = true;
368     } else if (clazz->obj.clazz != gDvm.classJavaLangClass) {
369         LOGW("JNI WARNING: jclass does not point to class object (%p - %s)\n",
370             jclazz, clazz->descriptor);
371         printWarn = true;
372     } else {
373         checkObject(env, jclazz, func);
374     }
375
376     if (printWarn)
377         abortMaybe();
378
379     JNI_EXIT();
380 }
381
382 /*
383  * Verify that "str" is non-NULL and points to a String object.
384  *
385  * Since we're dealing with objects, switch to "running" mode.
386  */
387 static void checkString(JNIEnv* env, jstring str, const char* func)
388 {
389     JNI_ENTER();
390     bool printWarn = false;
391
392     Object* obj = (Object*) str;
393
394     if (obj == NULL) {
395         LOGW("JNI WARNING: received null jstring (%s)\n", func);
396         printWarn = true;
397     } else if (obj->clazz != gDvm.classJavaLangString) {
398         if (dvmIsValidObject(obj))
399             LOGW("JNI WARNING: jstring points to non-string object (%s)\n",
400                 func);
401         else
402             LOGW("JNI WARNING: jstring %p is bogus (%s)\n", str, func);
403         printWarn = true;
404     } else {
405         checkObject(env, str, func);
406     }
407
408     if (printWarn)
409         abortMaybe();
410
411     JNI_EXIT();
412 }
413
414 /*
415  * Verify that "bytes" points to valid "modified UTF-8" data.
416  */
417 static void checkUtfString(JNIEnv* env, const char* bytes, bool nullOk,
418     const char* func)
419 {
420     const char* origBytes = bytes;
421
422     if (bytes == NULL) {
423         if (!nullOk) {
424             LOGW("JNI WARNING: unexpectedly null UTF string\n");
425             goto fail;
426         }
427
428         return;
429     }
430
431     while (*bytes != '\0') {
432         u1 utf8 = *(bytes++);
433         // Switch on the high four bits.
434         switch (utf8 >> 4) {
435             case 0x00:
436             case 0x01:
437             case 0x02:
438             case 0x03:
439             case 0x04:
440             case 0x05:
441             case 0x06:
442             case 0x07: {
443                 // Bit pattern 0xxx. No need for any extra bytes.
444                 break;
445             }
446             case 0x08:
447             case 0x09:
448             case 0x0a:
449             case 0x0b:
450             case 0x0f: {
451                 /*
452                  * Bit pattern 10xx or 1111, which are illegal start bytes.
453                  * Note: 1111 is valid for normal UTF-8, but not the
454                  * modified UTF-8 used here.
455                  */
456                 LOGW("JNI WARNING: illegal start byte 0x%x\n", utf8);
457                 goto fail;
458             }
459             case 0x0e: {
460                 // Bit pattern 1110, so there are two additional bytes.
461                 utf8 = *(bytes++);
462                 if ((utf8 & 0xc0) != 0x80) {
463                     LOGW("JNI WARNING: illegal continuation byte 0x%x\n", utf8);
464                     goto fail;
465                 }
466                 // Fall through to take care of the final byte.
467             }
468             case 0x0c:
469             case 0x0d: {
470                 // Bit pattern 110x, so there is one additional byte.
471                 utf8 = *(bytes++);
472                 if ((utf8 & 0xc0) != 0x80) {
473                     LOGW("JNI WARNING: illegal continuation byte 0x%x\n", utf8);
474                     goto fail;
475                 }
476                 break;
477             }
478         }
479     }
480
481     return;
482
483 fail:
484     LOGW("             string: '%s'\n", origBytes);
485     showLocation(dvmGetCurrentJNIMethod(), func);
486     abortMaybe();
487 }
488
489 /*
490  * In some circumstances the VM will screen class names, but it doesn't
491  * for class lookup.  When things get bounced through a class loader, they
492  * can actually get normalized a couple of times; as a result, passing in
493  * a class name like "java.lang.Thread" instead of "java/lang/Thread" will
494  * work in some circumstances.
495  *
496  * This is incorrect and could cause strange behavior or compatibility
497  * problems, so we want to screen that out here.
498  *
499  * We expect "full-qualified" class names, like "java/lang/Thread" or
500  * "[Ljava/lang/Object;".
501  */
502 static void checkClassName(JNIEnv* env, const char* className, const char* func)
503 {
504     const char* cp;
505
506     /* quick check for illegal chars */
507     cp = className;
508     while (*cp != '\0') {
509         if (*cp == '.')
510             goto fail;
511         cp++;
512     }
513
514     // TODO: need a more rigorous check here
515
516     return;
517
518 fail:
519     LOGW("JNI WARNING: illegal class name '%s' (%s)\n", className, func);
520     abortMaybe();
521 }
522
523 /*
524  * Verify that "array" is non-NULL and points to an Array object.
525  *
526  * Since we're dealing with objects, switch to "running" mode.
527  */
528 static void checkArray(JNIEnv* env, jarray array, const char* func)
529 {
530     JNI_ENTER();
531     bool printWarn = false;
532
533     Object* obj = (Object*) array;
534
535     if (obj == NULL) {
536         LOGW("JNI WARNING: received null array (%s)\n", func);
537         printWarn = true;
538     } else if (obj->clazz->descriptor[0] != '[') {
539         if (dvmIsValidObject(obj))
540             LOGW("JNI WARNING: jarray points to non-array object\n");
541         else
542             LOGW("JNI WARNING: jarray is bogus (%p)\n", array);
543         printWarn = true;
544     } else {
545         checkObject(env, array, func);
546     }
547
548     if (printWarn)
549         abortMaybe();
550
551     JNI_EXIT();
552 }
553
554 /*
555  * Verify that the "mode" argument passed to a primitive array Release
556  * function is one of the valid values.
557  */
558 static void checkReleaseMode(JNIEnv* env, jint mode, const char* func)
559 {
560     if (mode != 0 && mode != JNI_COMMIT && mode != JNI_ABORT) {
561         LOGW("JNI WARNING: bad value for mode (%d) (%s)\n", mode, func);
562         abortMaybe();
563     }
564 }
565
566 /*
567  * Verify that the length argument to array-creation calls is >= 0.
568  */
569 static void checkLengthPositive(JNIEnv* env, jsize length, const char* func)
570 {
571     if (length < 0) {
572         LOGW("JNI WARNING: negative length for array allocation (%s)\n", func);
573         abortMaybe();
574     }
575 }
576
577 /*
578  * Verify that the pointer value is non-NULL.
579  */
580 static void checkNonNull(JNIEnv* env, const void* ptr, const char* func)
581 {
582     if (ptr == NULL) {
583         LOGW("JNI WARNING: invalid null pointer (%s)\n", func);
584         abortMaybe();
585     }
586 }
587
588 /*
589  * Verify that the method's return type matches the type of call.
590  *
591  * "expectedSigByte" will be 'L' for all objects, including arrays.
592  */
593 static void checkSig(JNIEnv* env, jmethodID methodID, char expectedSigByte,
594     bool isStatic, const char* func)
595 {
596     const Method* meth = (const Method*) methodID;
597     bool printWarn = false;
598
599     if (expectedSigByte != meth->shorty[0]) {
600         LOGW("JNI WARNING: expected return type '%c'\n", expectedSigByte);
601         printWarn = true;
602     } else if (isStatic && !dvmIsStaticMethod(meth)) {
603         if (isStatic)
604             LOGW("JNI WARNING: calling non-static method with static call\n");
605         else
606             LOGW("JNI WARNING: calling static method with non-static call\n");
607         printWarn = true;
608     }
609
610     if (printWarn) {
611         char* desc = dexProtoCopyMethodDescriptor(&meth->prototype);
612         LOGW("             calling %s.%s %s\n",
613             meth->clazz->descriptor, meth->name, desc);
614         free(desc);
615         showLocation(dvmGetCurrentJNIMethod(), func);
616         abortMaybe();
617     }
618 }
619
620 /*
621  * Verify that this static field ID is valid for this class.
622  */
623 static void checkStaticFieldID(JNIEnv* env, jclass clazz, jfieldID fieldID)
624 {
625     StaticField* base = ((ClassObject*) clazz)->sfields;
626     int fieldCount = ((ClassObject*) clazz)->sfieldCount;
627
628     if ((StaticField*) fieldID < base ||
629         (StaticField*) fieldID >= base + fieldCount)
630     {
631         LOGW("JNI WARNING: static fieldID %p not valid for class %s\n",
632             fieldID, ((ClassObject*) clazz)->descriptor);
633         LOGW("             base=%p count=%d\n", base, fieldCount);
634         abortMaybe();
635     }
636 }
637
638 /*
639  * Verify that this instance field ID is valid for this object.
640  */
641 static void checkInstanceFieldID(JNIEnv* env, jobject obj, jfieldID fieldID)
642 {
643     ClassObject* clazz = ((Object*)obj)->clazz;
644
645     /*
646      * Check this class and all of its superclasses for a matching field.
647      * Don't need to scan interfaces.
648      */
649     while (clazz != NULL) {
650         if ((InstField*) fieldID >= clazz->ifields &&
651             (InstField*) fieldID < clazz->ifields + clazz->ifieldCount)
652         {
653             return;
654         }
655
656         clazz = clazz->super;
657     }
658
659     LOGW("JNI WARNING: inst fieldID %p not valid for class %s\n",
660         fieldID, ((Object*)obj)->clazz->descriptor);
661     abortMaybe();
662 }
663
664
665 /*
666  * ===========================================================================
667  *      Guarded arrays
668  * ===========================================================================
669  */
670
671 #define kGuardLen       512         /* must be multiple of 2 */
672 #define kGuardPattern   0xd5e3      /* uncommon values; d5e3d5e3 invalid addr */
673 #define kGuardMagic     0xffd5aa96
674 #define kGuardExtra     sizeof(GuardExtra)
675
676 /* this gets tucked in at the start of the buffer; struct size must be even */
677 typedef struct GuardExtra {
678     u4          magic;
679     uLong       adler;
680     size_t      originalLen;
681     const void* originalPtr;
682 } GuardExtra;
683
684 /* find the GuardExtra given the pointer into the "live" data */
685 inline static GuardExtra* getGuardExtra(const void* dataBuf)
686 {
687     u1* fullBuf = ((u1*) dataBuf) - kGuardLen / 2;
688     return (GuardExtra*) fullBuf;
689 }
690
691 /*
692  * Create an oversized buffer to hold the contents of "buf".  Copy it in,
693  * filling in the area around it with guard data.
694  *
695  * We use a 16-bit pattern to make a rogue memset less likely to elude us.
696  */
697 static void* createGuardedCopy(const void* buf, size_t len, bool modOkay)
698 {
699     GuardExtra* pExtra;
700     size_t newLen = (len + kGuardLen +1) & ~0x01;
701     u1* newBuf;
702     u2* pat;
703     int i;
704
705     newBuf = (u1*)malloc(newLen);
706     if (newBuf == NULL) {
707         LOGE("createGuardedCopy failed on alloc of %d bytes\n", newLen);
708         dvmAbort();
709     }
710
711     /* fill it in with a pattern */
712     pat = (u2*) newBuf;
713     for (i = 0; i < (int)newLen / 2; i++)
714         *pat++ = kGuardPattern;
715
716     /* copy the data in; note "len" could be zero */
717     memcpy(newBuf + kGuardLen / 2, buf, len);
718
719     /* if modification is not expected, grab a checksum */
720     uLong adler = 0;
721     if (!modOkay) {
722         adler = adler32(0L, Z_NULL, 0);
723         adler = adler32(adler, buf, len);
724         *(uLong*)newBuf = adler;
725     }
726
727     pExtra = (GuardExtra*) newBuf;
728     pExtra->magic = kGuardMagic;
729     pExtra->adler = adler;
730     pExtra->originalPtr = buf;
731     pExtra->originalLen = len;
732
733     return newBuf + kGuardLen / 2;
734 }
735
736 /*
737  * Verify the guard area and, if "modOkay" is false, that the data itself
738  * has not been altered.
739  */
740 static bool checkGuardedCopy(const void* dataBuf, bool modOkay)
741 {
742     const u1* fullBuf = ((const u1*) dataBuf) - kGuardLen / 2;
743     const GuardExtra* pExtra = getGuardExtra(dataBuf);
744     size_t len = pExtra->originalLen;
745     const u2* pat;
746     int i;
747
748     if (pExtra->magic != kGuardMagic) {
749         LOGE("JNI: guard magic does not match (found 0x%08x) "
750              "-- incorrect data pointer %p?\n",
751             pExtra->magic, dataBuf);
752         return false;
753     }
754
755     /* check bottom half of guard; skip over optional checksum storage */
756     pat = (u2*) fullBuf;
757     for (i = kGuardExtra / 2; i < (int) (kGuardLen / 2 - kGuardExtra) / 2; i++)
758     {
759         if (pat[i] != kGuardPattern) {
760             LOGE("JNI: guard pattern(1) disturbed at %p + %d\n",
761                 fullBuf, i*2);
762             return false;
763         }
764     }
765
766     int offset = kGuardLen / 2 + len;
767     if (offset & 0x01) {
768         /* odd byte; expected value depends on endian-ness of host */
769         const u2 patSample = kGuardPattern;
770         if (fullBuf[offset] != ((const u1*) &patSample)[1]) {
771             LOGE("JNI: guard pattern disturbed in odd byte after %p "
772                  "(+%d) 0x%02x 0x%02x\n",
773                 fullBuf, offset, fullBuf[offset], ((const u1*) &patSample)[1]);
774             return false;
775         }
776         offset++;
777     }
778
779     /* check top half of guard */
780     pat = (u2*) (fullBuf + offset);
781     for (i = 0; i < kGuardLen / 4; i++) {
782         if (pat[i] != kGuardPattern) {
783             LOGE("JNI: guard pattern(2) disturbed at %p + %d\n",
784                 fullBuf, offset + i*2);
785             return false;
786         }
787     }
788
789     /*
790      * If modification is not expected, verify checksum.  Strictly speaking
791      * this is wrong: if we told the client that we made a copy, there's no
792      * reason they can't alter the buffer.
793      */
794     if (!modOkay) {
795         uLong adler = adler32(0L, Z_NULL, 0);
796         adler = adler32(adler, dataBuf, len);
797         if (pExtra->adler != adler) {
798             LOGE("JNI: buffer modified (0x%08lx vs 0x%08lx) at addr %p\n",
799                 pExtra->adler, adler, dataBuf);
800             return false;
801         }
802     }
803
804     return true;
805 }
806
807 /*
808  * Free up the guard buffer, scrub it, and return the original pointer.
809  */
810 static void* freeGuardedCopy(void* dataBuf)
811 {
812     u1* fullBuf = ((u1*) dataBuf) - kGuardLen / 2;
813     const GuardExtra* pExtra = getGuardExtra(dataBuf);
814     void* originalPtr = (void*) pExtra->originalPtr;
815     size_t len = pExtra->originalLen;
816
817     memset(dataBuf, len, 0xdd);
818     free(fullBuf);
819     return originalPtr;
820 }
821
822 /*
823  * Just pull out the original pointer.
824  */
825 static void* getGuardedCopyOriginalPtr(const void* dataBuf)
826 {
827     const GuardExtra* pExtra = getGuardExtra(dataBuf);
828     return (void*) pExtra->originalPtr;
829 }
830
831 /*
832  * Grab the data length.
833  */
834 static size_t getGuardedCopyOriginalLen(const void* dataBuf)
835 {
836     const GuardExtra* pExtra = getGuardExtra(dataBuf);
837     return pExtra->originalLen;
838 }
839
840 /*
841  * Return the width, in bytes, of a primitive type.
842  */
843 static int dvmPrimitiveTypeWidth(PrimitiveType primType)
844 {
845     static const int lengths[PRIM_MAX] = {
846         1,      // boolean
847         2,      // char
848         4,      // float
849         8,      // double
850         1,      // byte
851         2,      // short
852         4,      // int
853         8,      // long
854         -1,     // void
855     };
856     assert(primType >= 0 && primType < PRIM_MAX);
857     return lengths[primType];
858 }
859
860 /*
861  * Create a guarded copy of a primitive array.  Modifications to the copied
862  * data are allowed.  Returns a pointer to the copied data.
863  */
864 static void* createGuardedPACopy(const ArrayObject* array, jboolean* isCopy)
865 {
866     PrimitiveType primType = array->obj.clazz->elementClass->primitiveType;
867     int len = array->length * dvmPrimitiveTypeWidth(primType);
868     void* result;
869
870     result = createGuardedCopy(array->contents, len, true);
871
872     if (isCopy != NULL)
873         *isCopy = JNI_TRUE;
874
875     return result;
876 }
877
878 /*
879  * Perform the array "release" operation, which may or may not copy data
880  * back into the VM, and may or may not release the underlying storage.
881  */
882 static void* releaseGuardedPACopy(ArrayObject* array, void* dataBuf, int mode)
883 {
884     PrimitiveType primType = array->obj.clazz->elementClass->primitiveType;
885     //int len = array->length * dvmPrimitiveTypeWidth(primType);
886     bool release, copyBack;
887     u1* result;
888
889     if (!checkGuardedCopy(dataBuf, true)) {
890         LOGE("JNI: failed guarded copy check in releaseGuardedPACopy\n");
891         abortMaybe();
892     }
893
894     switch (mode) {
895     case 0:
896         release = copyBack = true;
897         break;
898     case JNI_ABORT:
899         release = true;
900         copyBack = false;
901         break;
902     case JNI_COMMIT:
903         release = false;
904         copyBack = true;
905         break;
906     default:
907         LOGE("JNI: bad release mode %d\n", mode);
908         dvmAbort();
909         return NULL;
910     }
911
912     if (copyBack) {
913         size_t len = getGuardedCopyOriginalLen(dataBuf);
914         memcpy(array->contents, dataBuf, len);
915     }
916
917     if (release) {
918         result = (u1*) freeGuardedCopy(dataBuf);
919     } else {
920         result = (u1*) getGuardedCopyOriginalPtr(dataBuf);
921     }
922
923     /* pointer is to the array contents; back up to the array object */
924     result -= offsetof(ArrayObject, contents);
925
926     return result;
927 }
928
929
930 /*
931  * ===========================================================================
932  *      JNI functions
933  * ===========================================================================
934  */
935
936 static jint Check_GetVersion(JNIEnv* env)
937 {
938     CHECK_ENTER(env, kFlag_Default);
939     jint result;
940     result = BASE_ENV(env)->GetVersion(env);
941     CHECK_EXIT(env);
942     return result;
943 }
944
945 static jclass Check_DefineClass(JNIEnv* env, const char* name, jobject loader,
946     const jbyte* buf, jsize bufLen)
947 {
948     CHECK_ENTER(env, kFlag_Default);
949     CHECK_OBJECT(env, loader);
950     CHECK_UTF_STRING(env, name, false);
951     CHECK_CLASS_NAME(env, name);
952     jclass result;
953     result = BASE_ENV(env)->DefineClass(env, name, loader, buf, bufLen);
954     CHECK_EXIT(env);
955     return result;
956 }
957
958 static jclass Check_FindClass(JNIEnv* env, const char* name)
959 {
960     CHECK_ENTER(env, kFlag_Default);
961     CHECK_UTF_STRING(env, name, false);
962     CHECK_CLASS_NAME(env, name);
963     jclass result;
964     result = BASE_ENV(env)->FindClass(env, name);
965     CHECK_EXIT(env);
966     return result;
967 }
968
969 static jclass Check_GetSuperclass(JNIEnv* env, jclass clazz)
970 {
971     CHECK_ENTER(env, kFlag_Default);
972     CHECK_CLASS(env, clazz);
973     jclass result;
974     result = BASE_ENV(env)->GetSuperclass(env, clazz);
975     CHECK_EXIT(env);
976     return result;
977 }
978
979 static jboolean Check_IsAssignableFrom(JNIEnv* env, jclass clazz1,
980     jclass clazz2)
981 {
982     CHECK_ENTER(env, kFlag_Default);
983     CHECK_CLASS(env, clazz1);
984     CHECK_CLASS(env, clazz2);
985     jboolean result;
986     result = BASE_ENV(env)->IsAssignableFrom(env, clazz1, clazz2);
987     CHECK_EXIT(env);
988     return result;
989 }
990
991 static jmethodID Check_FromReflectedMethod(JNIEnv* env, jobject method)
992 {
993     CHECK_ENTER(env, kFlag_Default);
994     CHECK_OBJECT(env, method);
995     jmethodID result;
996     result = BASE_ENV(env)->FromReflectedMethod(env, method);
997     CHECK_EXIT(env);
998     return result;
999 }
1000
1001 static jfieldID Check_FromReflectedField(JNIEnv* env, jobject field)
1002 {
1003     CHECK_ENTER(env, kFlag_Default);
1004     CHECK_OBJECT(env, field);
1005     jfieldID result;
1006     result = BASE_ENV(env)->FromReflectedField(env, field);
1007     CHECK_EXIT(env);
1008     return result;
1009 }
1010
1011 static jobject Check_ToReflectedMethod(JNIEnv* env, jclass cls,
1012     jmethodID methodID, jboolean isStatic)
1013 {
1014     CHECK_ENTER(env, kFlag_Default);
1015     CHECK_CLASS(env, cls);
1016     jobject result;
1017     result = BASE_ENV(env)->ToReflectedMethod(env, cls, methodID, isStatic);
1018     CHECK_EXIT(env);
1019     return result;
1020 }
1021
1022 static jobject Check_ToReflectedField(JNIEnv* env, jclass cls, jfieldID fieldID,
1023     jboolean isStatic)
1024 {
1025     CHECK_ENTER(env, kFlag_Default);
1026     CHECK_CLASS(env, cls);
1027     jobject result;
1028     result = BASE_ENV(env)->ToReflectedField(env, cls, fieldID, isStatic);
1029     CHECK_EXIT(env);
1030     return result;
1031 }
1032
1033 static jint Check_Throw(JNIEnv* env, jthrowable obj)
1034 {
1035     CHECK_ENTER(env, kFlag_Default);
1036     CHECK_OBJECT(env, obj);
1037     jint result;
1038     result = BASE_ENV(env)->Throw(env, obj);
1039     CHECK_EXIT(env);
1040     return result;
1041 }
1042
1043 static jint Check_ThrowNew(JNIEnv* env, jclass clazz, const char* message)
1044 {
1045     CHECK_ENTER(env, kFlag_Default);
1046     CHECK_CLASS(env, clazz);
1047     CHECK_UTF_STRING(env, message, true);
1048     jint result;
1049     result = BASE_ENV(env)->ThrowNew(env, clazz, message);
1050     CHECK_EXIT(env);
1051     return result;
1052 }
1053
1054 static jthrowable Check_ExceptionOccurred(JNIEnv* env)
1055 {
1056     CHECK_ENTER(env, kFlag_ExcepOkay);
1057     jthrowable result;
1058     result = BASE_ENV(env)->ExceptionOccurred(env);
1059     CHECK_EXIT(env);
1060     return result;
1061 }
1062
1063 static void Check_ExceptionDescribe(JNIEnv* env)
1064 {
1065     CHECK_ENTER(env, kFlag_ExcepOkay);
1066     BASE_ENV(env)->ExceptionDescribe(env);
1067     CHECK_EXIT(env);
1068 }
1069
1070 static void Check_ExceptionClear(JNIEnv* env)
1071 {
1072     CHECK_ENTER(env, kFlag_ExcepOkay);
1073     BASE_ENV(env)->ExceptionClear(env);
1074     CHECK_EXIT(env);
1075 }
1076
1077 static void Check_FatalError(JNIEnv* env, const char* msg)
1078 {
1079     CHECK_ENTER(env, kFlag_Default);
1080     CHECK_UTF_STRING(env, msg, true);
1081     BASE_ENV(env)->FatalError(env, msg);
1082     CHECK_EXIT(env);
1083 }
1084
1085 static jint Check_PushLocalFrame(JNIEnv* env, jint capacity)
1086 {
1087     CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
1088     jint result;
1089     result = BASE_ENV(env)->PushLocalFrame(env, capacity);
1090     CHECK_EXIT(env);
1091     return result;
1092 }
1093
1094 static jobject Check_PopLocalFrame(JNIEnv* env, jobject res)
1095 {
1096     CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
1097     CHECK_OBJECT(env, res);
1098     jobject result;
1099     result = BASE_ENV(env)->PopLocalFrame(env, res);
1100     CHECK_EXIT(env);
1101     return result;
1102 }
1103
1104 static jobject Check_NewGlobalRef(JNIEnv* env, jobject obj)
1105 {
1106     CHECK_ENTER(env, kFlag_Default);
1107     CHECK_OBJECT(env, obj);
1108     jobject result;
1109     result = BASE_ENV(env)->NewGlobalRef(env, obj);
1110     CHECK_EXIT(env);
1111     return result;
1112 }
1113
1114 static void Check_DeleteGlobalRef(JNIEnv* env, jobject localRef)
1115 {
1116     CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
1117     CHECK_OBJECT(env, localRef);
1118     BASE_ENV(env)->DeleteGlobalRef(env, localRef);
1119     CHECK_EXIT(env);
1120 }
1121
1122 static jobject Check_NewLocalRef(JNIEnv* env, jobject ref)
1123 {
1124     CHECK_ENTER(env, kFlag_Default);
1125     CHECK_OBJECT(env, ref);
1126     jobject result;
1127     result = BASE_ENV(env)->NewLocalRef(env, ref);
1128     CHECK_EXIT(env);
1129     return result;
1130 }
1131
1132 static void Check_DeleteLocalRef(JNIEnv* env, jobject globalRef)
1133 {
1134     CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
1135     CHECK_OBJECT(env, globalRef);
1136     BASE_ENV(env)->DeleteLocalRef(env, globalRef);
1137     CHECK_EXIT(env);
1138 }
1139
1140 static jint Check_EnsureLocalCapacity(JNIEnv *env, jint capacity)
1141 {
1142     CHECK_ENTER(env, kFlag_Default);
1143     jint result;
1144     result = BASE_ENV(env)->EnsureLocalCapacity(env, capacity);
1145     CHECK_EXIT(env);
1146     return result;
1147 }
1148
1149 static jboolean Check_IsSameObject(JNIEnv* env, jobject ref1, jobject ref2)
1150 {
1151     CHECK_ENTER(env, kFlag_Default);
1152     CHECK_OBJECT(env, ref1);
1153     CHECK_OBJECT(env, ref2);
1154     jboolean result;
1155     result = BASE_ENV(env)->IsSameObject(env, ref1, ref2);
1156     CHECK_EXIT(env);
1157     return result;
1158 }
1159
1160 static jobject Check_AllocObject(JNIEnv* env, jclass clazz)
1161 {
1162     CHECK_ENTER(env, kFlag_Default);
1163     CHECK_CLASS(env, clazz);
1164     jobject result;
1165     result = BASE_ENV(env)->AllocObject(env, clazz);
1166     CHECK_EXIT(env);
1167     return result;
1168 }
1169
1170 static jobject Check_NewObject(JNIEnv* env, jclass clazz, jmethodID methodID,
1171     ...)
1172 {
1173     CHECK_ENTER(env, kFlag_Default);
1174     CHECK_CLASS(env, clazz);
1175     jobject result;
1176     va_list args;
1177
1178     va_start(args, methodID);
1179     result = BASE_ENV(env)->NewObjectV(env, clazz, methodID, args);
1180     va_end(args);
1181
1182     CHECK_EXIT(env);
1183     return result;
1184 }
1185 static jobject Check_NewObjectV(JNIEnv* env, jclass clazz, jmethodID methodID,
1186     va_list args)
1187 {
1188     CHECK_ENTER(env, kFlag_Default);
1189     CHECK_CLASS(env, clazz);
1190     jobject result;
1191     result = BASE_ENV(env)->NewObjectV(env, clazz, methodID, args);
1192     CHECK_EXIT(env);
1193     return result;
1194 }
1195 static jobject Check_NewObjectA(JNIEnv* env, jclass clazz, jmethodID methodID,
1196     jvalue* args)
1197 {
1198     CHECK_ENTER(env, kFlag_Default);
1199     CHECK_CLASS(env, clazz);
1200     jobject result;
1201     result = BASE_ENV(env)->NewObjectA(env, clazz, methodID, args);
1202     CHECK_EXIT(env);
1203     return result;
1204 }
1205
1206 static jclass Check_GetObjectClass(JNIEnv* env, jobject obj)
1207 {
1208     CHECK_ENTER(env, kFlag_Default);
1209     CHECK_OBJECT(env, obj);
1210     jclass result;
1211     result = BASE_ENV(env)->GetObjectClass(env, obj);
1212     CHECK_EXIT(env);
1213     return result;
1214 }
1215
1216 static jboolean Check_IsInstanceOf(JNIEnv* env, jobject obj, jclass clazz)
1217 {
1218     CHECK_ENTER(env, kFlag_Default);
1219     CHECK_OBJECT(env, obj);
1220     CHECK_CLASS(env, clazz);
1221     jboolean result;
1222     result = BASE_ENV(env)->IsInstanceOf(env, obj, clazz);
1223     CHECK_EXIT(env);
1224     return result;
1225 }
1226
1227 static jmethodID Check_GetMethodID(JNIEnv* env, jclass clazz, const char* name,
1228     const char* sig)
1229 {
1230     CHECK_ENTER(env, kFlag_Default);
1231     CHECK_CLASS(env, clazz);
1232     CHECK_UTF_STRING(env, name, false);
1233     CHECK_UTF_STRING(env, sig, false);
1234     jmethodID result;
1235     result = BASE_ENV(env)->GetMethodID(env, clazz, name, sig);
1236     CHECK_EXIT(env);
1237     return result;
1238 }
1239
1240 static jfieldID Check_GetFieldID(JNIEnv* env, jclass clazz,
1241     const char* name, const char* sig)
1242 {
1243     CHECK_ENTER(env, kFlag_Default);
1244     CHECK_CLASS(env, clazz);
1245     CHECK_UTF_STRING(env, name, false);
1246     CHECK_UTF_STRING(env, sig, false);
1247     jfieldID result;
1248     result = BASE_ENV(env)->GetFieldID(env, clazz, name, sig);
1249     CHECK_EXIT(env);
1250     return result;
1251 }
1252
1253 static jmethodID Check_GetStaticMethodID(JNIEnv* env, jclass clazz,
1254     const char* name, const char* sig)
1255 {
1256     CHECK_ENTER(env, kFlag_Default);
1257     CHECK_CLASS(env, clazz);
1258     CHECK_UTF_STRING(env, name, false);
1259     CHECK_UTF_STRING(env, sig, false);
1260     jmethodID result;
1261     result = BASE_ENV(env)->GetStaticMethodID(env, clazz, name, sig);
1262     CHECK_EXIT(env);
1263     return result;
1264 }
1265
1266 static jfieldID Check_GetStaticFieldID(JNIEnv* env, jclass clazz,
1267     const char* name, const char* sig)
1268 {
1269     CHECK_ENTER(env, kFlag_Default);
1270     CHECK_CLASS(env, clazz);
1271     CHECK_UTF_STRING(env, name, false);
1272     CHECK_UTF_STRING(env, sig, false);
1273     jfieldID result;
1274     result = BASE_ENV(env)->GetStaticFieldID(env, clazz, name, sig);
1275     CHECK_EXIT(env);
1276     return result;
1277 }
1278
1279 #define GET_STATIC_TYPE_FIELD(_ctype, _jname, _isref)                       \
1280     static _ctype Check_GetStatic##_jname##Field(JNIEnv* env, jclass clazz, \
1281         jfieldID fieldID)                                                   \
1282     {                                                                       \
1283         CHECK_ENTER(env, kFlag_Default);                                    \
1284         CHECK_CLASS(env, clazz);                                            \
1285         _ctype result;                                                      \
1286         checkStaticFieldID(env, clazz, fieldID);                            \
1287         result = BASE_ENV(env)->GetStatic##_jname##Field(env, clazz,        \
1288             fieldID);                                                       \
1289         CHECK_EXIT(env);                                                    \
1290         return result;                                                      \
1291     }
1292 GET_STATIC_TYPE_FIELD(jobject, Object, true);
1293 GET_STATIC_TYPE_FIELD(jboolean, Boolean, false);
1294 GET_STATIC_TYPE_FIELD(jbyte, Byte, false);
1295 GET_STATIC_TYPE_FIELD(jchar, Char, false);
1296 GET_STATIC_TYPE_FIELD(jshort, Short, false);
1297 GET_STATIC_TYPE_FIELD(jint, Int, false);
1298 GET_STATIC_TYPE_FIELD(jlong, Long, false);
1299 GET_STATIC_TYPE_FIELD(jfloat, Float, false);
1300 GET_STATIC_TYPE_FIELD(jdouble, Double, false);
1301
1302 #define SET_STATIC_TYPE_FIELD(_ctype, _jname, _ftype)                       \
1303     static void Check_SetStatic##_jname##Field(JNIEnv* env, jclass clazz,   \
1304         jfieldID fieldID, _ctype value)                                     \
1305     {                                                                       \
1306         CHECK_ENTER(env, kFlag_Default);                                    \
1307         CHECK_CLASS(env, clazz);                                            \
1308         checkStaticFieldID(env, clazz, fieldID);                            \
1309         CHECK_FIELD_TYPE((jobject)(u4)value, fieldID, _ftype, true);        \
1310         BASE_ENV(env)->SetStatic##_jname##Field(env, clazz, fieldID,        \
1311             value);                                                         \
1312         CHECK_EXIT(env);                                                    \
1313     }
1314 SET_STATIC_TYPE_FIELD(jobject, Object, PRIM_NOT);
1315 SET_STATIC_TYPE_FIELD(jboolean, Boolean, PRIM_BOOLEAN);
1316 SET_STATIC_TYPE_FIELD(jbyte, Byte, PRIM_BYTE);
1317 SET_STATIC_TYPE_FIELD(jchar, Char, PRIM_CHAR);
1318 SET_STATIC_TYPE_FIELD(jshort, Short, PRIM_SHORT);
1319 SET_STATIC_TYPE_FIELD(jint, Int, PRIM_INT);
1320 SET_STATIC_TYPE_FIELD(jlong, Long, PRIM_LONG);
1321 SET_STATIC_TYPE_FIELD(jfloat, Float, PRIM_FLOAT);
1322 SET_STATIC_TYPE_FIELD(jdouble, Double, PRIM_DOUBLE);
1323
1324 #define GET_TYPE_FIELD(_ctype, _jname, _isref)                              \
1325     static _ctype Check_Get##_jname##Field(JNIEnv* env, jobject obj,        \
1326         jfieldID fieldID)                                                   \
1327     {                                                                       \
1328         CHECK_ENTER(env, kFlag_Default);                                    \
1329         CHECK_OBJECT(env, obj);                                             \
1330         _ctype result;                                                      \
1331         checkInstanceFieldID(env, obj, fieldID);                            \
1332         result = BASE_ENV(env)->Get##_jname##Field(env, obj, fieldID);      \
1333         CHECK_EXIT(env);                                                    \
1334         return result;                                                      \
1335     }
1336 GET_TYPE_FIELD(jobject, Object, true);
1337 GET_TYPE_FIELD(jboolean, Boolean, false);
1338 GET_TYPE_FIELD(jbyte, Byte, false);
1339 GET_TYPE_FIELD(jchar, Char, false);
1340 GET_TYPE_FIELD(jshort, Short, false);
1341 GET_TYPE_FIELD(jint, Int, false);
1342 GET_TYPE_FIELD(jlong, Long, false);
1343 GET_TYPE_FIELD(jfloat, Float, false);
1344 GET_TYPE_FIELD(jdouble, Double, false);
1345
1346 #define SET_TYPE_FIELD(_ctype, _jname, _ftype)                              \
1347     static void Check_Set##_jname##Field(JNIEnv* env, jobject obj,          \
1348         jfieldID fieldID, _ctype value)                                     \
1349     {                                                                       \
1350         CHECK_ENTER(env, kFlag_Default);                                    \
1351         CHECK_OBJECT(env, obj);                                             \
1352         checkInstanceFieldID(env, obj, fieldID);                            \
1353         CHECK_FIELD_TYPE((jobject)(u4) value, fieldID, _ftype, false);      \
1354         BASE_ENV(env)->Set##_jname##Field(env, obj, fieldID, value);        \
1355         CHECK_EXIT(env);                                                    \
1356     }
1357 SET_TYPE_FIELD(jobject, Object, PRIM_NOT);
1358 SET_TYPE_FIELD(jboolean, Boolean, PRIM_BOOLEAN);
1359 SET_TYPE_FIELD(jbyte, Byte, PRIM_BYTE);
1360 SET_TYPE_FIELD(jchar, Char, PRIM_CHAR);
1361 SET_TYPE_FIELD(jshort, Short, PRIM_SHORT);
1362 SET_TYPE_FIELD(jint, Int, PRIM_INT);
1363 SET_TYPE_FIELD(jlong, Long, PRIM_LONG);
1364 SET_TYPE_FIELD(jfloat, Float, PRIM_FLOAT);
1365 SET_TYPE_FIELD(jdouble, Double, PRIM_DOUBLE);
1366
1367 #define CALL_VIRTUAL(_ctype, _jname, _retfail, _retdecl, _retasgn, _retok,  \
1368         _retsig)                                                            \
1369     static _ctype Check_Call##_jname##Method(JNIEnv* env, jobject obj,      \
1370         jmethodID methodID, ...)                                            \
1371     {                                                                       \
1372         CHECK_ENTER(env, kFlag_Default);                                    \
1373         CHECK_OBJECT(env, obj);                                             \
1374         CHECK_SIG(env, methodID, _retsig, false);                           \
1375         _retdecl;                                                           \
1376         va_list args;                                                       \
1377         va_start(args, methodID);                                           \
1378         _retasgn BASE_ENV(env)->Call##_jname##MethodV(env, obj, methodID,   \
1379             args);                                                          \
1380         va_end(args);                                                       \
1381         CHECK_EXIT(env);                                                    \
1382         return _retok;                                                      \
1383     }                                                                       \
1384     static _ctype Check_Call##_jname##MethodV(JNIEnv* env, jobject obj,     \
1385         jmethodID methodID, va_list args)                                   \
1386     {                                                                       \
1387         CHECK_ENTER(env, kFlag_Default);                                    \
1388         CHECK_OBJECT(env, obj);                                             \
1389         CHECK_SIG(env, methodID, _retsig, false);                           \
1390         _retdecl;                                                           \
1391         _retasgn BASE_ENV(env)->Call##_jname##MethodV(env, obj, methodID,   \
1392             args);                                                          \
1393         CHECK_EXIT(env);                                                    \
1394         return _retok;                                                      \
1395     }                                                                       \
1396     static _ctype Check_Call##_jname##MethodA(JNIEnv* env, jobject obj,     \
1397         jmethodID methodID, jvalue* args)                                   \
1398     {                                                                       \
1399         CHECK_ENTER(env, kFlag_Default);                                    \
1400         CHECK_OBJECT(env, obj);                                             \
1401         CHECK_SIG(env, methodID, _retsig, false);                           \
1402         _retdecl;                                                           \
1403         _retasgn BASE_ENV(env)->Call##_jname##MethodA(env, obj, methodID,   \
1404             args);                                                          \
1405         CHECK_EXIT(env);                                                    \
1406         return _retok;                                                      \
1407     }
1408 CALL_VIRTUAL(jobject, Object, NULL, Object* result, result=, result, 'L');
1409 CALL_VIRTUAL(jboolean, Boolean, 0, jboolean result, result=, result, 'Z');
1410 CALL_VIRTUAL(jbyte, Byte, 0, jbyte result, result=, result, 'B');
1411 CALL_VIRTUAL(jchar, Char, 0, jchar result, result=, result, 'C');
1412 CALL_VIRTUAL(jshort, Short, 0, jshort result, result=, result, 'S');
1413 CALL_VIRTUAL(jint, Int, 0, jint result, result=, result, 'I');
1414 CALL_VIRTUAL(jlong, Long, 0, jlong result, result=, result, 'J');
1415 CALL_VIRTUAL(jfloat, Float, 0.0f, jfloat result, result=, *(float*)&result, 'F');
1416 CALL_VIRTUAL(jdouble, Double, 0.0, jdouble result, result=, *(double*)&result, 'D');
1417 CALL_VIRTUAL(void, Void, , , , , 'V');
1418
1419 #define CALL_NONVIRTUAL(_ctype, _jname, _retfail, _retdecl, _retasgn,       \
1420         _retok, _retsig)                                                    \
1421     static _ctype Check_CallNonvirtual##_jname##Method(JNIEnv* env,         \
1422         jobject obj, jclass clazz, jmethodID methodID, ...)                 \
1423     {                                                                       \
1424         CHECK_ENTER(env, kFlag_Default);                                    \
1425         CHECK_CLASS(env, clazz);                                            \
1426         CHECK_OBJECT(env, obj);                                             \
1427         CHECK_SIG(env, methodID, _retsig, false);                           \
1428         _retdecl;                                                           \
1429         va_list args;                                                       \
1430         va_start(args, methodID);                                           \
1431         _retasgn BASE_ENV(env)->CallNonvirtual##_jname##MethodV(env, obj,   \
1432             clazz, methodID, args);                                         \
1433         va_end(args);                                                       \
1434         CHECK_EXIT(env);                                                    \
1435         return _retok;                                                      \
1436     }                                                                       \
1437     static _ctype Check_CallNonvirtual##_jname##MethodV(JNIEnv* env,        \
1438         jobject obj, jclass clazz, jmethodID methodID, va_list args)        \
1439     {                                                                       \
1440         CHECK_ENTER(env, kFlag_Default);                                    \
1441         CHECK_CLASS(env, clazz);                                            \
1442         CHECK_OBJECT(env, obj);                                             \
1443         CHECK_SIG(env, methodID, _retsig, false);                           \
1444         _retdecl;                                                           \
1445         _retasgn BASE_ENV(env)->CallNonvirtual##_jname##MethodV(env, obj,   \
1446             clazz, methodID, args);                                         \
1447         CHECK_EXIT(env);                                                    \
1448         return _retok;                                                      \
1449     }                                                                       \
1450     static _ctype Check_CallNonvirtual##_jname##MethodA(JNIEnv* env,        \
1451         jobject obj, jclass clazz, jmethodID methodID, jvalue* args)        \
1452     {                                                                       \
1453         CHECK_ENTER(env, kFlag_Default);                                    \
1454         CHECK_CLASS(env, clazz);                                            \
1455         CHECK_OBJECT(env, obj);                                             \
1456         CHECK_SIG(env, methodID, _retsig, false);                           \
1457         _retdecl;                                                           \
1458         _retasgn BASE_ENV(env)->CallNonvirtual##_jname##MethodA(env, obj,   \
1459             clazz, methodID, args);                                         \
1460         CHECK_EXIT(env);                                                    \
1461         return _retok;                                                      \
1462     }
1463 CALL_NONVIRTUAL(jobject, Object, NULL, Object* result, result=, (Object*)(u4)result, 'L');
1464 CALL_NONVIRTUAL(jboolean, Boolean, 0, jboolean result, result=, result, 'Z');
1465 CALL_NONVIRTUAL(jbyte, Byte, 0, jbyte result, result=, result, 'B');
1466 CALL_NONVIRTUAL(jchar, Char, 0, jchar result, result=, result, 'C');
1467 CALL_NONVIRTUAL(jshort, Short, 0, jshort result, result=, result, 'S');
1468 CALL_NONVIRTUAL(jint, Int, 0, jint result, result=, result, 'I');
1469 CALL_NONVIRTUAL(jlong, Long, 0, jlong result, result=, result, 'J');
1470 CALL_NONVIRTUAL(jfloat, Float, 0.0f, jfloat result, result=, *(float*)&result, 'F');
1471 CALL_NONVIRTUAL(jdouble, Double, 0.0, jdouble result, result=, *(double*)&result, 'D');
1472 CALL_NONVIRTUAL(void, Void, , , , , 'V');
1473
1474
1475 #define CALL_STATIC(_ctype, _jname, _retfail, _retdecl, _retasgn, _retok,   \
1476         _retsig)                                                            \
1477     static _ctype Check_CallStatic##_jname##Method(JNIEnv* env,             \
1478         jclass clazz, jmethodID methodID, ...)                              \
1479     {                                                                       \
1480         CHECK_ENTER(env, kFlag_Default);                                    \
1481         CHECK_CLASS(env, clazz);                                            \
1482         CHECK_SIG(env, methodID, _retsig, true);                            \
1483         _retdecl;                                                           \
1484         va_list args;                                                       \
1485         va_start(args, methodID);                                           \
1486         _retasgn BASE_ENV(env)->CallStatic##_jname##MethodV(env, clazz,     \
1487             methodID, args);                                                \
1488         va_end(args);                                                       \
1489         CHECK_EXIT(env);                                                    \
1490         return _retok;                                                      \
1491     }                                                                       \
1492     static _ctype Check_CallStatic##_jname##MethodV(JNIEnv* env,            \
1493         jclass clazz, jmethodID methodID, va_list args)                     \
1494     {                                                                       \
1495         CHECK_ENTER(env, kFlag_Default);                                    \
1496         CHECK_CLASS(env, clazz);                                            \
1497         CHECK_SIG(env, methodID, _retsig, true);                            \
1498         _retdecl;                                                           \
1499         _retasgn BASE_ENV(env)->CallStatic##_jname##MethodV(env, clazz,     \
1500             methodID, args);                                                \
1501         CHECK_EXIT(env);                                                    \
1502         return _retok;                                                      \
1503     }                                                                       \
1504     static _ctype Check_CallStatic##_jname##MethodA(JNIEnv* env,            \
1505         jclass clazz, jmethodID methodID, jvalue* args)                     \
1506     {                                                                       \
1507         CHECK_ENTER(env, kFlag_Default);                                    \
1508         CHECK_CLASS(env, clazz);                                            \
1509         CHECK_SIG(env, methodID, _retsig, true);                            \
1510         _retdecl;                                                           \
1511         _retasgn BASE_ENV(env)->CallStatic##_jname##MethodA(env, clazz,     \
1512             methodID, args);                                                \
1513         CHECK_EXIT(env);                                                    \
1514         return _retok;                                                      \
1515     }
1516 CALL_STATIC(jobject, Object, NULL, Object* result, result=, (Object*)(u4)result, 'L');
1517 CALL_STATIC(jboolean, Boolean, 0, jboolean result, result=, result, 'Z');
1518 CALL_STATIC(jbyte, Byte, 0, jbyte result, result=, result, 'B');
1519 CALL_STATIC(jchar, Char, 0, jchar result, result=, result, 'C');
1520 CALL_STATIC(jshort, Short, 0, jshort result, result=, result, 'S');
1521 CALL_STATIC(jint, Int, 0, jint result, result=, result, 'I');
1522 CALL_STATIC(jlong, Long, 0, jlong result, result=, result, 'J');
1523 CALL_STATIC(jfloat, Float, 0.0f, jfloat result, result=, *(float*)&result, 'F');
1524 CALL_STATIC(jdouble, Double, 0.0, jdouble result, result=, *(double*)&result, 'D');
1525 CALL_STATIC(void, Void, , , , , 'V');
1526
1527 static jstring Check_NewString(JNIEnv* env, const jchar* unicodeChars,
1528     jsize len)
1529 {
1530     CHECK_ENTER(env, kFlag_Default);
1531     jstring result;
1532     result = BASE_ENV(env)->NewString(env, unicodeChars, len);
1533     CHECK_EXIT(env);
1534     return result;
1535 }
1536
1537 static jsize Check_GetStringLength(JNIEnv* env, jstring string)
1538 {
1539     CHECK_ENTER(env, kFlag_CritOkay);
1540     CHECK_STRING(env, string);
1541     jsize result;
1542     result = BASE_ENV(env)->GetStringLength(env, string);
1543     CHECK_EXIT(env);
1544     return result;
1545 }
1546
1547 static const jchar* Check_GetStringChars(JNIEnv* env, jstring string,
1548     jboolean* isCopy)
1549 {
1550     CHECK_ENTER(env, kFlag_CritOkay);
1551     CHECK_STRING(env, string);
1552     const jchar* result;
1553     result = BASE_ENV(env)->GetStringChars(env, string, isCopy);
1554     if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) {
1555         int len = dvmStringLen(string) * 2;
1556         result = (const jchar*) createGuardedCopy(result, len, false);
1557         if (isCopy != NULL)
1558             *isCopy = JNI_TRUE;
1559     }
1560     CHECK_EXIT(env);
1561     return result;
1562 }
1563
1564 static void Check_ReleaseStringChars(JNIEnv* env, jstring string,
1565     const jchar* chars)
1566 {
1567     CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
1568     CHECK_STRING(env, string);
1569     CHECK_NON_NULL(env, chars);
1570     if (((JNIEnvExt*)env)->forceDataCopy) {
1571         if (!checkGuardedCopy(chars, false)) {
1572             LOGE("JNI: failed guarded copy check in ReleaseStringChars\n");
1573             abortMaybe();
1574         }
1575         chars = (const jchar*) freeGuardedCopy((jchar*)chars);
1576     }
1577     BASE_ENV(env)->ReleaseStringChars(env, string, chars);
1578     CHECK_EXIT(env);
1579 }
1580
1581 static jstring Check_NewStringUTF(JNIEnv* env, const char* bytes)
1582 {
1583     CHECK_ENTER(env, kFlag_Default);
1584     CHECK_UTF_STRING(env, bytes, true);
1585     jstring result;
1586     result = BASE_ENV(env)->NewStringUTF(env, bytes);
1587     CHECK_EXIT(env);
1588     return result;
1589 }
1590
1591 static jsize Check_GetStringUTFLength(JNIEnv* env, jstring string)
1592 {
1593     CHECK_ENTER(env, kFlag_CritOkay);
1594     CHECK_STRING(env, string);
1595     jsize result;
1596     result = BASE_ENV(env)->GetStringUTFLength(env, string);
1597     CHECK_EXIT(env);
1598     return result;
1599 }
1600
1601 static const char* Check_GetStringUTFChars(JNIEnv* env, jstring string,
1602     jboolean* isCopy)
1603 {
1604     CHECK_ENTER(env, kFlag_CritOkay);
1605     CHECK_STRING(env, string);
1606     const char* result;
1607     result = BASE_ENV(env)->GetStringUTFChars(env, string, isCopy);
1608     if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) {
1609         int len = dvmStringUtf8ByteLen(string) + 1;
1610         result = (const char*) createGuardedCopy(result, len, false);
1611         if (isCopy != NULL)
1612             *isCopy = JNI_TRUE;
1613     }
1614     CHECK_EXIT(env);
1615     return result;
1616 }
1617
1618 static void Check_ReleaseStringUTFChars(JNIEnv* env, jstring string,
1619     const char* utf)
1620 {
1621     CHECK_ENTER(env, kFlag_ExcepOkay);
1622     CHECK_STRING(env, string);
1623     CHECK_NON_NULL(env, utf);
1624     if (((JNIEnvExt*)env)->forceDataCopy) {
1625         //int len = dvmStringUtf8ByteLen(string) + 1;
1626         if (!checkGuardedCopy(utf, false)) {
1627             LOGE("JNI: failed guarded copy check in ReleaseStringUTFChars\n");
1628             abortMaybe();
1629         }
1630         utf = (const char*) freeGuardedCopy((char*)utf);
1631     }
1632     BASE_ENV(env)->ReleaseStringUTFChars(env, string, utf);
1633     CHECK_EXIT(env);
1634 }
1635
1636 static jsize Check_GetArrayLength(JNIEnv* env, jarray array)
1637 {
1638     CHECK_ENTER(env, kFlag_CritOkay);
1639     CHECK_ARRAY(env, array);
1640     jsize result;
1641     result = BASE_ENV(env)->GetArrayLength(env, array);
1642     CHECK_EXIT(env);
1643     return result;
1644 }
1645
1646 static jobjectArray Check_NewObjectArray(JNIEnv* env, jsize length,
1647     jclass elementClass, jobject initialElement)
1648 {
1649     CHECK_ENTER(env, kFlag_Default);
1650     CHECK_CLASS(env, elementClass);
1651     CHECK_OBJECT(env, initialElement);
1652     CHECK_LENGTH_POSITIVE(env, length);
1653     jobjectArray result;
1654     result = BASE_ENV(env)->NewObjectArray(env, length, elementClass,
1655                                             initialElement);
1656     CHECK_EXIT(env);
1657     return result;
1658 }
1659
1660 static jobject Check_GetObjectArrayElement(JNIEnv* env, jobjectArray array,
1661     jsize index)
1662 {
1663     CHECK_ENTER(env, kFlag_Default);
1664     CHECK_ARRAY(env, array);
1665     jobject result;
1666     result = BASE_ENV(env)->GetObjectArrayElement(env, array, index);
1667     CHECK_EXIT(env);
1668     return result;
1669 }
1670
1671 static void Check_SetObjectArrayElement(JNIEnv* env, jobjectArray array,
1672     jsize index, jobject value)
1673 {
1674     CHECK_ENTER(env, kFlag_Default);
1675     CHECK_ARRAY(env, array);
1676     BASE_ENV(env)->SetObjectArrayElement(env, array, index, value);
1677     CHECK_EXIT(env);
1678 }
1679
1680 #define NEW_PRIMITIVE_ARRAY(_artype, _jname)                                \
1681     static _artype Check_New##_jname##Array(JNIEnv* env, jsize length)      \
1682     {                                                                       \
1683         CHECK_ENTER(env, kFlag_Default);                                    \
1684         CHECK_LENGTH_POSITIVE(env, length);                                 \
1685         _artype result;                                                     \
1686         result = BASE_ENV(env)->New##_jname##Array(env, length);            \
1687         CHECK_EXIT(env);                                                    \
1688         return result;                                                      \
1689     }
1690 NEW_PRIMITIVE_ARRAY(jbooleanArray, Boolean);
1691 NEW_PRIMITIVE_ARRAY(jbyteArray, Byte);
1692 NEW_PRIMITIVE_ARRAY(jcharArray, Char);
1693 NEW_PRIMITIVE_ARRAY(jshortArray, Short);
1694 NEW_PRIMITIVE_ARRAY(jintArray, Int);
1695 NEW_PRIMITIVE_ARRAY(jlongArray, Long);
1696 NEW_PRIMITIVE_ARRAY(jfloatArray, Float);
1697 NEW_PRIMITIVE_ARRAY(jdoubleArray, Double);
1698
1699
1700 #define GET_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname)                        \
1701     static _ctype* Check_Get##_jname##ArrayElements(JNIEnv* env,            \
1702         _ctype##Array array, jboolean* isCopy)                              \
1703     {                                                                       \
1704         CHECK_ENTER(env, kFlag_Default);                                    \
1705         CHECK_ARRAY(env, array);                                            \
1706         _ctype* result;                                                     \
1707         result = BASE_ENV(env)->Get##_jname##ArrayElements(env,             \
1708             array, isCopy);                                                 \
1709         if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) {           \
1710             result = (_ctype*)                                              \
1711                 createGuardedPACopy((ArrayObject*) array, isCopy);          \
1712         }                                                                   \
1713         CHECK_EXIT(env);                                                    \
1714         return result;                                                      \
1715     }
1716
1717 #define RELEASE_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname)                    \
1718     static void Check_Release##_jname##ArrayElements(JNIEnv* env,           \
1719         _ctype##Array array, _ctype* elems, jint mode)                      \
1720     {                                                                       \
1721         CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);                  \
1722         CHECK_ARRAY(env, array);                                            \
1723         CHECK_NON_NULL(env, elems);                                         \
1724         CHECK_RELEASE_MODE(env, mode);                                      \
1725         if (((JNIEnvExt*)env)->forceDataCopy) {                             \
1726             elems = (_ctype*) releaseGuardedPACopy((ArrayObject*) array,    \
1727                 elems, mode);                                               \
1728         }                                                                   \
1729         BASE_ENV(env)->Release##_jname##ArrayElements(env,                  \
1730             array, elems, mode);                                            \
1731         CHECK_EXIT(env);                                                    \
1732     }
1733
1734 #define GET_PRIMITIVE_ARRAY_REGION(_ctype, _jname)                          \
1735     static void Check_Get##_jname##ArrayRegion(JNIEnv* env,                 \
1736         _ctype##Array array, jsize start, jsize len, _ctype* buf)           \
1737     {                                                                       \
1738         CHECK_ENTER(env, kFlag_Default);                                    \
1739         CHECK_ARRAY(env, array);                                            \
1740         BASE_ENV(env)->Get##_jname##ArrayRegion(env, array, start,          \
1741             len, buf);                                                      \
1742         CHECK_EXIT(env);                                                    \
1743     }
1744
1745 #define SET_PRIMITIVE_ARRAY_REGION(_ctype, _jname)                          \
1746     static void Check_Set##_jname##ArrayRegion(JNIEnv* env,                 \
1747         _ctype##Array array, jsize start, jsize len, const _ctype* buf)     \
1748     {                                                                       \
1749         CHECK_ENTER(env, kFlag_Default);                                    \
1750         CHECK_ARRAY(env, array);                                            \
1751         BASE_ENV(env)->Set##_jname##ArrayRegion(env, array, start,          \
1752             len, buf);                                                      \
1753         CHECK_EXIT(env);                                                    \
1754     }
1755
1756 #define PRIMITIVE_ARRAY_FUNCTIONS(_ctype, _jname, _typechar)                \
1757     GET_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname);                           \
1758     RELEASE_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname);                       \
1759     GET_PRIMITIVE_ARRAY_REGION(_ctype, _jname);                             \
1760     SET_PRIMITIVE_ARRAY_REGION(_ctype, _jname);
1761
1762 /* TODO: verify primitive array type matches call type */
1763 PRIMITIVE_ARRAY_FUNCTIONS(jboolean, Boolean, 'Z');
1764 PRIMITIVE_ARRAY_FUNCTIONS(jbyte, Byte, 'B');
1765 PRIMITIVE_ARRAY_FUNCTIONS(jchar, Char, 'C');
1766 PRIMITIVE_ARRAY_FUNCTIONS(jshort, Short, 'S');
1767 PRIMITIVE_ARRAY_FUNCTIONS(jint, Int, 'I');
1768 PRIMITIVE_ARRAY_FUNCTIONS(jlong, Long, 'J');
1769 PRIMITIVE_ARRAY_FUNCTIONS(jfloat, Float, 'F');
1770 PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, 'D');
1771
1772 static jint Check_RegisterNatives(JNIEnv* env, jclass clazz,
1773     const JNINativeMethod* methods, jint nMethods)
1774 {
1775     CHECK_ENTER(env, kFlag_Default);
1776     CHECK_CLASS(env, clazz);
1777     jint result;
1778     result = BASE_ENV(env)->RegisterNatives(env, clazz, methods, nMethods);
1779     CHECK_EXIT(env);
1780     return result;
1781 }
1782
1783 static jint Check_UnregisterNatives(JNIEnv* env, jclass clazz)
1784 {
1785     CHECK_ENTER(env, kFlag_Default);
1786     CHECK_CLASS(env, clazz);
1787     jint result;
1788     result = BASE_ENV(env)->UnregisterNatives(env, clazz);
1789     CHECK_EXIT(env);
1790     return result;
1791 }
1792
1793 static jint Check_MonitorEnter(JNIEnv* env, jobject obj)
1794 {
1795     CHECK_ENTER(env, kFlag_Default);
1796     CHECK_OBJECT(env, obj);
1797     jint result;
1798     result = BASE_ENV(env)->MonitorEnter(env, obj);
1799     CHECK_EXIT(env);
1800     return result;
1801 }
1802
1803 static jint Check_MonitorExit(JNIEnv* env, jobject obj)
1804 {
1805     CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
1806     CHECK_OBJECT(env, obj);
1807     jint result;
1808     result = BASE_ENV(env)->MonitorExit(env, obj);
1809     CHECK_EXIT(env);
1810     return result;
1811 }
1812
1813 static jint Check_GetJavaVM(JNIEnv *env, JavaVM **vm)
1814 {
1815     CHECK_ENTER(env, kFlag_Default);
1816     jint result;
1817     result = BASE_ENV(env)->GetJavaVM(env, vm);
1818     CHECK_EXIT(env);
1819     return result;
1820 }
1821
1822 static void Check_GetStringRegion(JNIEnv* env, jstring str, jsize start,
1823     jsize len, jchar* buf)
1824 {
1825     CHECK_ENTER(env, kFlag_CritOkay);
1826     CHECK_STRING(env, str);
1827     BASE_ENV(env)->GetStringRegion(env, str, start, len, buf);
1828     CHECK_EXIT(env);
1829 }
1830
1831 static void Check_GetStringUTFRegion(JNIEnv* env, jstring str, jsize start,
1832     jsize len, char* buf)
1833 {
1834     CHECK_ENTER(env, kFlag_CritOkay);
1835     CHECK_STRING(env, str);
1836     BASE_ENV(env)->GetStringUTFRegion(env, str, start, len, buf);
1837     CHECK_EXIT(env);
1838 }
1839
1840 static void* Check_GetPrimitiveArrayCritical(JNIEnv* env, jarray array,
1841     jboolean* isCopy)
1842 {
1843     CHECK_ENTER(env, kFlag_CritGet);
1844     CHECK_ARRAY(env, array);
1845     void* result;
1846     result = BASE_ENV(env)->GetPrimitiveArrayCritical(env, array, isCopy);
1847     if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) {
1848         result = createGuardedPACopy((ArrayObject*) array, isCopy);
1849     }
1850     CHECK_EXIT(env);
1851     return result;
1852 }
1853
1854 static void Check_ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array,
1855     void* carray, jint mode)
1856 {
1857     CHECK_ENTER(env, kFlag_CritRelease | kFlag_ExcepOkay);
1858     CHECK_ARRAY(env, array);
1859     CHECK_NON_NULL(env, carray);
1860     CHECK_RELEASE_MODE(env, mode);
1861     if (((JNIEnvExt*)env)->forceDataCopy) {
1862         carray = releaseGuardedPACopy((ArrayObject*) array, carray, mode);
1863     }
1864     BASE_ENV(env)->ReleasePrimitiveArrayCritical(env, array, carray, mode);
1865     CHECK_EXIT(env);
1866 }
1867
1868 static const jchar* Check_GetStringCritical(JNIEnv* env, jstring string,
1869     jboolean* isCopy)
1870 {
1871     CHECK_ENTER(env, kFlag_CritGet);
1872     CHECK_STRING(env, string);
1873     const jchar* result;
1874     result = BASE_ENV(env)->GetStringCritical(env, string, isCopy);
1875     if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) {
1876         int len = dvmStringLen(string) * 2;
1877         result = (const jchar*) createGuardedCopy(result, len, false);
1878         if (isCopy != NULL)
1879             *isCopy = JNI_TRUE;
1880     }
1881     CHECK_EXIT(env);
1882     return result;
1883 }
1884
1885 static void Check_ReleaseStringCritical(JNIEnv* env, jstring string,
1886     const jchar* carray)
1887 {
1888     CHECK_ENTER(env, kFlag_CritRelease | kFlag_ExcepOkay);
1889     CHECK_STRING(env, string);
1890     CHECK_NON_NULL(env, carray);
1891     if (((JNIEnvExt*)env)->forceDataCopy) {
1892         if (!checkGuardedCopy(carray, false)) {
1893             LOGE("JNI: failed guarded copy check in ReleaseStringCritical\n");
1894             abortMaybe();
1895         }
1896         carray = (const jchar*) freeGuardedCopy((jchar*)carray);
1897     }
1898     BASE_ENV(env)->ReleaseStringCritical(env, string, carray);
1899     CHECK_EXIT(env);
1900 }
1901
1902 static jweak Check_NewWeakGlobalRef(JNIEnv* env, jobject obj)
1903 {
1904     CHECK_ENTER(env, kFlag_Default);
1905     CHECK_OBJECT(env, obj);
1906     jweak result;
1907     result = BASE_ENV(env)->NewWeakGlobalRef(env, obj);
1908     CHECK_EXIT(env);
1909     return result;
1910 }
1911
1912 static void Check_DeleteWeakGlobalRef(JNIEnv* env, jweak obj)
1913 {
1914     CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
1915     CHECK_OBJECT(env, obj);
1916     BASE_ENV(env)->DeleteWeakGlobalRef(env, obj);
1917     CHECK_EXIT(env);
1918 }
1919
1920 static jboolean Check_ExceptionCheck(JNIEnv* env)
1921 {
1922     CHECK_ENTER(env, kFlag_CritOkay | kFlag_ExcepOkay);
1923     jboolean result;
1924     result = BASE_ENV(env)->ExceptionCheck(env);
1925     CHECK_EXIT(env);
1926     return result;
1927 }
1928
1929 static jobjectRefType Check_GetObjectRefType(JNIEnv* env, jobject obj)
1930 {
1931     CHECK_ENTER(env, kFlag_Default);
1932     CHECK_OBJECT(env, obj);
1933     jobjectRefType result;
1934     result = BASE_ENV(env)->GetObjectRefType(env, obj);
1935     CHECK_EXIT(env);
1936     return result;
1937 }
1938
1939 static jobject Check_NewDirectByteBuffer(JNIEnv* env, void* address,
1940     jlong capacity)
1941 {
1942     CHECK_ENTER(env, kFlag_Default);
1943     jobject result;
1944     if (address == NULL || capacity < 0) {
1945         LOGW("JNI WARNING: invalid values for address (%p) or capacity (%ld)\n",
1946             address, (long) capacity);
1947         abortMaybe();
1948     }
1949     result = BASE_ENV(env)->NewDirectByteBuffer(env, address, capacity);
1950     CHECK_EXIT(env);
1951     return result;
1952 }
1953
1954 static void* Check_GetDirectBufferAddress(JNIEnv* env, jobject buf)
1955 {
1956     CHECK_ENTER(env, kFlag_Default);
1957     CHECK_OBJECT(env, buf);
1958     void* result;
1959     //if (buf == NULL)
1960     //    result = NULL;
1961     //else
1962         result = BASE_ENV(env)->GetDirectBufferAddress(env, buf);
1963     CHECK_EXIT(env);
1964     return result;
1965 }
1966
1967 static jlong Check_GetDirectBufferCapacity(JNIEnv* env, jobject buf)
1968 {
1969     CHECK_ENTER(env, kFlag_Default);
1970     CHECK_OBJECT(env, buf);
1971     jlong result;
1972     //if (buf == NULL)
1973     //    result = -1;
1974     //else
1975         result = BASE_ENV(env)->GetDirectBufferCapacity(env, buf);
1976     CHECK_EXIT(env);
1977     return result;
1978 }
1979
1980
1981 /*
1982  * ===========================================================================
1983  *      JNI invocation functions
1984  * ===========================================================================
1985  */
1986
1987 static jint Check_DestroyJavaVM(JavaVM* vm)
1988 {
1989     CHECK_VMENTER(vm, false);
1990     jint result;
1991     result = BASE_VM(vm)->DestroyJavaVM(vm);
1992     CHECK_VMEXIT(vm, false);
1993     return result;
1994 }
1995
1996 static jint Check_AttachCurrentThread(JavaVM* vm, JNIEnv** p_env,
1997     void* thr_args)
1998 {
1999     CHECK_VMENTER(vm, false);
2000     jint result;
2001     result = BASE_VM(vm)->AttachCurrentThread(vm, p_env, thr_args);
2002     CHECK_VMEXIT(vm, true);
2003     return result;
2004 }
2005
2006 static jint Check_AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env,
2007     void* thr_args)
2008 {
2009     CHECK_VMENTER(vm, false);
2010     jint result;
2011     result = BASE_VM(vm)->AttachCurrentThreadAsDaemon(vm, p_env, thr_args);
2012     CHECK_VMEXIT(vm, true);
2013     return result;
2014 }
2015
2016 static jint Check_DetachCurrentThread(JavaVM* vm)
2017 {
2018     CHECK_VMENTER(vm, true);
2019     jint result;
2020     result = BASE_VM(vm)->DetachCurrentThread(vm);
2021     CHECK_VMEXIT(vm, false);
2022     return result;
2023 }
2024
2025 static jint Check_GetEnv(JavaVM* vm, void** env, jint version)
2026 {
2027     CHECK_VMENTER(vm, true);
2028     jint result;
2029     result = BASE_VM(vm)->GetEnv(vm, env, version);
2030     CHECK_VMEXIT(vm, true);
2031     return result;
2032 }
2033
2034
2035 /*
2036  * ===========================================================================
2037  *      Function tables
2038  * ===========================================================================
2039  */
2040
2041 static const struct JNINativeInterface gCheckNativeInterface = {
2042     NULL,
2043     NULL,
2044     NULL,
2045     NULL,
2046
2047     Check_GetVersion,
2048
2049     Check_DefineClass,
2050     Check_FindClass,
2051
2052     Check_FromReflectedMethod,
2053     Check_FromReflectedField,
2054     Check_ToReflectedMethod,
2055
2056     Check_GetSuperclass,
2057     Check_IsAssignableFrom,
2058
2059     Check_ToReflectedField,
2060
2061     Check_Throw,
2062     Check_ThrowNew,
2063     Check_ExceptionOccurred,
2064     Check_ExceptionDescribe,
2065     Check_ExceptionClear,
2066     Check_FatalError,
2067
2068     Check_PushLocalFrame,
2069     Check_PopLocalFrame,
2070
2071     Check_NewGlobalRef,
2072     Check_DeleteGlobalRef,
2073     Check_DeleteLocalRef,
2074     Check_IsSameObject,
2075     Check_NewLocalRef,
2076     Check_EnsureLocalCapacity,
2077
2078     Check_AllocObject,
2079     Check_NewObject,
2080     Check_NewObjectV,
2081     Check_NewObjectA,
2082
2083     Check_GetObjectClass,
2084     Check_IsInstanceOf,
2085
2086     Check_GetMethodID,
2087
2088     Check_CallObjectMethod,
2089     Check_CallObjectMethodV,
2090     Check_CallObjectMethodA,
2091     Check_CallBooleanMethod,
2092     Check_CallBooleanMethodV,
2093     Check_CallBooleanMethodA,
2094     Check_CallByteMethod,
2095     Check_CallByteMethodV,
2096     Check_CallByteMethodA,
2097     Check_CallCharMethod,
2098     Check_CallCharMethodV,
2099     Check_CallCharMethodA,
2100     Check_CallShortMethod,
2101     Check_CallShortMethodV,
2102     Check_CallShortMethodA,
2103     Check_CallIntMethod,
2104     Check_CallIntMethodV,
2105     Check_CallIntMethodA,
2106     Check_CallLongMethod,
2107     Check_CallLongMethodV,
2108     Check_CallLongMethodA,
2109     Check_CallFloatMethod,
2110     Check_CallFloatMethodV,
2111     Check_CallFloatMethodA,
2112     Check_CallDoubleMethod,
2113     Check_CallDoubleMethodV,
2114     Check_CallDoubleMethodA,
2115     Check_CallVoidMethod,
2116     Check_CallVoidMethodV,
2117     Check_CallVoidMethodA,
2118
2119     Check_CallNonvirtualObjectMethod,
2120     Check_CallNonvirtualObjectMethodV,
2121     Check_CallNonvirtualObjectMethodA,
2122     Check_CallNonvirtualBooleanMethod,
2123     Check_CallNonvirtualBooleanMethodV,
2124     Check_CallNonvirtualBooleanMethodA,
2125     Check_CallNonvirtualByteMethod,
2126     Check_CallNonvirtualByteMethodV,
2127     Check_CallNonvirtualByteMethodA,
2128     Check_CallNonvirtualCharMethod,
2129     Check_CallNonvirtualCharMethodV,
2130     Check_CallNonvirtualCharMethodA,
2131     Check_CallNonvirtualShortMethod,
2132     Check_CallNonvirtualShortMethodV,
2133     Check_CallNonvirtualShortMethodA,
2134     Check_CallNonvirtualIntMethod,
2135     Check_CallNonvirtualIntMethodV,
2136     Check_CallNonvirtualIntMethodA,
2137     Check_CallNonvirtualLongMethod,
2138     Check_CallNonvirtualLongMethodV,
2139     Check_CallNonvirtualLongMethodA,
2140     Check_CallNonvirtualFloatMethod,
2141     Check_CallNonvirtualFloatMethodV,
2142     Check_CallNonvirtualFloatMethodA,
2143     Check_CallNonvirtualDoubleMethod,
2144     Check_CallNonvirtualDoubleMethodV,
2145     Check_CallNonvirtualDoubleMethodA,
2146     Check_CallNonvirtualVoidMethod,
2147     Check_CallNonvirtualVoidMethodV,
2148     Check_CallNonvirtualVoidMethodA,
2149
2150     Check_GetFieldID,
2151
2152     Check_GetObjectField,
2153     Check_GetBooleanField,
2154     Check_GetByteField,
2155     Check_GetCharField,
2156     Check_GetShortField,
2157     Check_GetIntField,
2158     Check_GetLongField,
2159     Check_GetFloatField,
2160     Check_GetDoubleField,
2161     Check_SetObjectField,
2162     Check_SetBooleanField,
2163     Check_SetByteField,
2164     Check_SetCharField,
2165     Check_SetShortField,
2166     Check_SetIntField,
2167     Check_SetLongField,
2168     Check_SetFloatField,
2169     Check_SetDoubleField,
2170
2171     Check_GetStaticMethodID,
2172
2173     Check_CallStaticObjectMethod,
2174     Check_CallStaticObjectMethodV,
2175     Check_CallStaticObjectMethodA,
2176     Check_CallStaticBooleanMethod,
2177     Check_CallStaticBooleanMethodV,
2178     Check_CallStaticBooleanMethodA,
2179     Check_CallStaticByteMethod,
2180     Check_CallStaticByteMethodV,
2181     Check_CallStaticByteMethodA,
2182     Check_CallStaticCharMethod,
2183     Check_CallStaticCharMethodV,
2184     Check_CallStaticCharMethodA,
2185     Check_CallStaticShortMethod,
2186     Check_CallStaticShortMethodV,
2187     Check_CallStaticShortMethodA,
2188     Check_CallStaticIntMethod,
2189     Check_CallStaticIntMethodV,
2190     Check_CallStaticIntMethodA,
2191     Check_CallStaticLongMethod,
2192     Check_CallStaticLongMethodV,
2193     Check_CallStaticLongMethodA,
2194     Check_CallStaticFloatMethod,
2195     Check_CallStaticFloatMethodV,
2196     Check_CallStaticFloatMethodA,
2197     Check_CallStaticDoubleMethod,
2198     Check_CallStaticDoubleMethodV,
2199     Check_CallStaticDoubleMethodA,
2200     Check_CallStaticVoidMethod,
2201     Check_CallStaticVoidMethodV,
2202     Check_CallStaticVoidMethodA,
2203
2204     Check_GetStaticFieldID,
2205
2206     Check_GetStaticObjectField,
2207     Check_GetStaticBooleanField,
2208     Check_GetStaticByteField,
2209     Check_GetStaticCharField,
2210     Check_GetStaticShortField,
2211     Check_GetStaticIntField,
2212     Check_GetStaticLongField,
2213     Check_GetStaticFloatField,
2214     Check_GetStaticDoubleField,
2215
2216     Check_SetStaticObjectField,
2217     Check_SetStaticBooleanField,
2218     Check_SetStaticByteField,
2219     Check_SetStaticCharField,
2220     Check_SetStaticShortField,
2221     Check_SetStaticIntField,
2222     Check_SetStaticLongField,
2223     Check_SetStaticFloatField,
2224     Check_SetStaticDoubleField,
2225
2226     Check_NewString,
2227
2228     Check_GetStringLength,
2229     Check_GetStringChars,
2230     Check_ReleaseStringChars,
2231
2232     Check_NewStringUTF,
2233     Check_GetStringUTFLength,
2234     Check_GetStringUTFChars,
2235     Check_ReleaseStringUTFChars,
2236
2237     Check_GetArrayLength,
2238     Check_NewObjectArray,
2239     Check_GetObjectArrayElement,
2240     Check_SetObjectArrayElement,
2241
2242     Check_NewBooleanArray,
2243     Check_NewByteArray,
2244     Check_NewCharArray,
2245     Check_NewShortArray,
2246     Check_NewIntArray,
2247     Check_NewLongArray,
2248     Check_NewFloatArray,
2249     Check_NewDoubleArray,
2250
2251     Check_GetBooleanArrayElements,
2252     Check_GetByteArrayElements,
2253     Check_GetCharArrayElements,
2254     Check_GetShortArrayElements,
2255     Check_GetIntArrayElements,
2256     Check_GetLongArrayElements,
2257     Check_GetFloatArrayElements,
2258     Check_GetDoubleArrayElements,
2259
2260     Check_ReleaseBooleanArrayElements,
2261     Check_ReleaseByteArrayElements,
2262     Check_ReleaseCharArrayElements,
2263     Check_ReleaseShortArrayElements,
2264     Check_ReleaseIntArrayElements,
2265     Check_ReleaseLongArrayElements,
2266     Check_ReleaseFloatArrayElements,
2267     Check_ReleaseDoubleArrayElements,
2268
2269     Check_GetBooleanArrayRegion,
2270     Check_GetByteArrayRegion,
2271     Check_GetCharArrayRegion,
2272     Check_GetShortArrayRegion,
2273     Check_GetIntArrayRegion,
2274     Check_GetLongArrayRegion,
2275     Check_GetFloatArrayRegion,
2276     Check_GetDoubleArrayRegion,
2277     Check_SetBooleanArrayRegion,
2278     Check_SetByteArrayRegion,
2279     Check_SetCharArrayRegion,
2280     Check_SetShortArrayRegion,
2281     Check_SetIntArrayRegion,
2282     Check_SetLongArrayRegion,
2283     Check_SetFloatArrayRegion,
2284     Check_SetDoubleArrayRegion,
2285
2286     Check_RegisterNatives,
2287     Check_UnregisterNatives,
2288
2289     Check_MonitorEnter,
2290     Check_MonitorExit,
2291
2292     Check_GetJavaVM,
2293
2294     Check_GetStringRegion,
2295     Check_GetStringUTFRegion,
2296
2297     Check_GetPrimitiveArrayCritical,
2298     Check_ReleasePrimitiveArrayCritical,
2299
2300     Check_GetStringCritical,
2301     Check_ReleaseStringCritical,
2302
2303     Check_NewWeakGlobalRef,
2304     Check_DeleteWeakGlobalRef,
2305
2306     Check_ExceptionCheck,
2307
2308     Check_NewDirectByteBuffer,
2309     Check_GetDirectBufferAddress,
2310     Check_GetDirectBufferCapacity,
2311
2312     Check_GetObjectRefType
2313 };
2314 static const struct JNIInvokeInterface gCheckInvokeInterface = {
2315     NULL,
2316     NULL,
2317     NULL,
2318
2319     Check_DestroyJavaVM,
2320     Check_AttachCurrentThread,
2321     Check_DetachCurrentThread,
2322
2323     Check_GetEnv,
2324
2325     Check_AttachCurrentThreadAsDaemon,
2326 };
2327
2328
2329 /*
2330  * Replace the normal table with the checked table.
2331  */
2332 void dvmUseCheckedJniEnv(JNIEnvExt* pEnv)
2333 {
2334     assert(pEnv->funcTable != &gCheckNativeInterface);
2335     pEnv->baseFuncTable = pEnv->funcTable;
2336     pEnv->funcTable = &gCheckNativeInterface;
2337 }
2338
2339 /*
2340  * Replace the normal table with the checked table.
2341  */
2342 void dvmUseCheckedJniVm(JavaVMExt* pVm)
2343 {
2344     assert(pVm->funcTable != &gCheckInvokeInterface);
2345     pVm->baseFuncTable = pVm->funcTable;
2346     pVm->funcTable = &gCheckInvokeInterface;
2347 }
2348