OSDN Git Service

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