diff options
Diffstat (limited to 'libjava/jni.cc')
-rw-r--r-- | libjava/jni.cc | 94 |
1 files changed, 81 insertions, 13 deletions
diff --git a/libjava/jni.cc b/libjava/jni.cc index b841b4fc481..7dd98364118 100644 --- a/libjava/jni.cc +++ b/libjava/jni.cc @@ -1,6 +1,6 @@ // jni.cc - JNI implementation, including the jump table. -/* Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation +/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation This file is part of libgcj. @@ -10,6 +10,7 @@ details. */ #include <config.h> +#include <stdio.h> #include <stddef.h> #include <string.h> @@ -1388,6 +1389,7 @@ static jarray elementClass = unwrap (elementClass); init = unwrap (init); + _Jv_CheckCast (elementClass, init); jarray result = JvNewObjectArray (length, elementClass, init); return (jarray) wrap_value (env, result); } @@ -1402,6 +1404,8 @@ static jobject (JNICALL _Jv_JNI_GetObjectArrayElement) (JNIEnv *env, jobjectArray array, jsize index) { + if ((unsigned) index >= (unsigned) array->length) + _Jv_ThrowBadArrayIndex (index); jobject *elts = elements (unwrap (array)); return wrap_value (env, elts[index]); } @@ -1416,6 +1420,8 @@ static void value = unwrap (value); _Jv_CheckArrayStore (array, value); + if ((unsigned) index >= (unsigned) array->length) + _Jv_ThrowBadArrayIndex (index); jobject *elts = elements (array); elts[index] = value; } @@ -2023,9 +2029,9 @@ _Jv_GetJNIEnvNewFrame (jclass klass) // This is `extern "C"' because the compiler uses it. extern "C" void * _Jv_LookupJNIMethod (jclass klass, _Jv_Utf8Const *name, - _Jv_Utf8Const *signature) + _Jv_Utf8Const *signature, int args_size) { - char buf[10 + 6 * (name->length + signature->length)]; + char buf[10 + 6 * (name->length + signature->length) + 12]; int long_start; void *function; @@ -2045,18 +2051,72 @@ _Jv_LookupJNIMethod (jclass klass, _Jv_Utf8Const *name, return function; // If there was no override, then look in the symbol table. - mangled_name (klass, name, signature, buf, &long_start); - char c = buf[long_start]; - buf[long_start] = '\0'; - function = _Jv_FindSymbolInExecutable (buf); + buf[0] = '_'; + mangled_name (klass, name, signature, buf + 1, &long_start); + char c = buf[long_start + 1]; + buf[long_start + 1] = '\0'; + + function = _Jv_FindSymbolInExecutable (buf + 1); +#ifdef WIN32 + // On Win32, we use the "stdcall" calling convention (see JNICALL + // in jni.h). + // + // For a function named 'fooBar' that takes 'nn' bytes as arguments, + // by default, MinGW GCC exports it as 'fooBar@nn', MSVC exports it + // as '_fooBar@nn' and Borland C exports it as 'fooBar'. We try to + // take care of all these variations here. + + char asz_buf[12]; /* '@' + '2147483647' (32-bit INT_MAX) + '\0' */ + char long_nm_sv[11]; /* Ditto, except for the '\0'. */ + if (function == NULL) { - buf[long_start] = c; + // We have tried searching for the 'fooBar' form (BCC) - now + // try the others. + + // First, save the part of the long name that will be damaged + // by appending '@nn'. + memcpy (long_nm_sv, (buf + long_start + 1 + 1), sizeof (long_nm_sv)); + + sprintf (asz_buf, "@%d", args_size); + strcat (buf, asz_buf); + + // Search for the '_fooBar@nn' form (MSVC). function = _Jv_FindSymbolInExecutable (buf); + + if (function == NULL) + { + // Search for the 'fooBar@nn' form (MinGW GCC). + function = _Jv_FindSymbolInExecutable (buf + 1); + } + } +#else /* WIN32 */ + args_size; /* Dummy statement to avoid unused parameter warning */ +#endif /* ! WIN32 */ + + if (function == NULL) + { + buf[long_start + 1] = c; +#ifdef WIN32 + // Restore the part of the long name that was damaged by + // appending the '@nn'. + memcpy ((buf + long_start + 1 + 1), long_nm_sv, sizeof (long_nm_sv)); +#endif /* WIN32 */ + function = _Jv_FindSymbolInExecutable (buf + 1); if (function == NULL) { - jstring str = JvNewStringUTF (name->data); - throw new java::lang::UnsatisfiedLinkError (str); +#ifdef WIN32 + strcat (buf, asz_buf); + function = _Jv_FindSymbolInExecutable (buf); + if (function == NULL) + function = _Jv_FindSymbolInExecutable (buf + 1); + + if (function == NULL) +#endif /* WIN32 */ + { + jstring str = JvNewStringUTF (name->data); + throw new java::lang::UnsatisfiedLinkError (str); + } } } @@ -2087,9 +2147,17 @@ _Jv_JNIMethod::call (ffi_cif *, void *ret, ffi_raw *args, void *__this) // time. JvSynchronize sync (global_ref_table); if (_this->function == NULL) - _this->function = _Jv_LookupJNIMethod (_this->defining_class, - _this->self->name, - _this->self->signature); + { + int args_size = sizeof (JNIEnv *) + _this->args_raw_size; + + if (_this->self->accflags & java::lang::reflect::Modifier::STATIC) + args_size += sizeof (_this->defining_class); + + _this->function = _Jv_LookupJNIMethod (_this->defining_class, + _this->self->name, + _this->self->signature, + args_size); + } } JvAssert (_this->args_raw_size % sizeof (ffi_raw) == 0); |