示例#1
0
static void
invokeArray(JNIEnv* env, jlong ctxAddress, jbyteArray paramBuffer, void* returnBuffer)
{
    Function* ctx = (Function *) j2p(ctxAddress);
    union { double d; long long ll; jbyte tmp[PARAM_SIZE]; } tmpStackBuffer[MAX_STACK_ARGS];
    jbyte *tmpBuffer = (jbyte *) &tmpStackBuffer[0];
    
    if (ctx->cif.nargs > 0) {
        if (ctx->cif.bytes > (int) sizeof(tmpStackBuffer)) {
            tmpBuffer = alloca_aligned(ctx->cif.bytes, MIN_ALIGN);
        }

        // calculate room needed for return address for struct returns
        int adj = ctx->cif.rtype->type == FFI_TYPE_STRUCT ? sizeof(void *) : 0;

        (*env)->GetByteArrayRegion(env, paramBuffer, 0, ctx->rawParameterSize, tmpBuffer + adj);
    }

    // For struct return values, we need to push a return value address on the parameter stack
    if (ctx->cif.rtype->type == FFI_TYPE_STRUCT) {
        *(void **) tmpBuffer = returnBuffer;
    }

    ffi_raw_call(&ctx->cif, FFI_FN(ctx->function), returnBuffer, (ffi_raw *) tmpBuffer);
    set_last_error(errno);
}
示例#2
0
static void
invokeArray(JNIEnv* env, jlong ctxAddress, jbyteArray paramBuffer, void* returnBuffer)
{
    Function* ctx = (Function *) j2p(ctxAddress);
    union { double d; long long ll; jbyte tmp[PARAM_SIZE]; } tmpStackBuffer[MAX_STACK_ARGS];
    jbyte *tmpBuffer = (jbyte *) &tmpStackBuffer[0];
    void* ffiStackArgs[MAX_STACK_ARGS];
    void** ffiArgs = ffiStackArgs;
    
    if (ctx->cif.nargs > 0) {
        unsigned int i;
        if (ctx->cif.nargs > MAX_STACK_ARGS) {
            tmpBuffer = alloca_aligned(ctx->cif.nargs * PARAM_SIZE, MIN_ALIGN);
            ffiArgs = alloca_aligned(ctx->cif.nargs * sizeof(void *), MIN_ALIGN);
        }
        
        (*env)->GetByteArrayRegion(env, paramBuffer, 0, ctx->cif.nargs * PARAM_SIZE, tmpBuffer);

        for (i = 0; i < ctx->cif.nargs; ++i) {
            if (ctx->cif.arg_types[i]->type == FFI_TYPE_STRUCT) {
                ffiArgs[i] = *(void **) &tmpBuffer[i * PARAM_SIZE];
            } else {
                ffiArgs[i] = &tmpBuffer[i * PARAM_SIZE];
            }
        }
    }

    ffi_call(&ctx->cif, FFI_FN(ctx->function), returnBuffer, ffiArgs);
    set_last_error(errno);
}
示例#3
0
文件: Invoke.c 项目: Flameeyes/jffi
static void
invokeArray(JNIEnv* env, jlong ctxAddress, jbyteArray paramBuffer, void* returnBuffer)
{
    Function* ctx = (Function *) j2p(ctxAddress);

    void** ffiArgs = { NULL };
    jbyte *tmpBuffer = NULL;
    
    if (ctx->cif.nargs > 0) {
        unsigned int i;
        tmpBuffer = alloca(ctx->cif.nargs * PARAM_SIZE);
        ffiArgs = alloca(ctx->cif.nargs * sizeof(void *));
        
        (*env)->GetByteArrayRegion(env, paramBuffer, 0, ctx->cif.nargs * PARAM_SIZE, tmpBuffer);

        for (i = 0; i < ctx->cif.nargs; ++i) {
            if (unlikely(ctx->cif.arg_types[i]->type == FFI_TYPE_STRUCT)) {
                ffiArgs[i] = *(void **) &tmpBuffer[i * PARAM_SIZE];
            } else {
                ffiArgs[i] = &tmpBuffer[i * PARAM_SIZE];
            }
        }
    }

    ffi_call(&ctx->cif, FFI_FN(ctx->function), returnBuffer, ffiArgs);

    SAVE_ERRNO(ctx);
}
示例#4
0
pid_t fbg_argv_to_pid(char **argv) {
	pid_t pid = 0;
	int jid = 0;
	char *p = argv[1];

	if (argv[1] == NULL || argv[2] != NULL)
		return 0;
	if (*p != '%' && (*p < '0' || *p > '9'))
		return 0;
	if (*p == '%' && *(p + 1) == 0)
		return 0;
	for (p += 1; *p != 0; p++)
		if (*p < '0' || *p > '9')
			return 0;
	p = argv[1];
	if (*p == '%') {
		if ((jid = atoi(p + 1)) < 1)
			return 0;
		if ((pid = j2p(jid)) < 1) {
			printf("no such process\n");
			return 0;
		}
		return pid;
	}
	if ((pid = atoi(p)) < 1)
		return 0;
	if (selectjob(pid) == NULL) {
		printf("no such process\n");
		return 0;
	}
	return pid;
}
示例#5
0
文件: Invoke.c 项目: Flameeyes/jffi
/*
 * Class:     com_kenai_jffi_Foreign
 * Method:    invokeArrayReturnStruct
 * Signature: (J[B[B)V
 */
JNIEXPORT void JNICALL
Java_com_kenai_jffi_Foreign_invokeArrayReturnStruct(JNIEnv* env, jclass self, jlong ctxAddress,
        jbyteArray paramBuffer, jbyteArray returnBuffer, jint offset)
{
    Function* ctx = (Function *) j2p(ctxAddress);
    jbyte* retval = alloca(ctx->cif.rtype->size);
    jbyte* tmpBuffer;
    void** ffiArgs;
    int i;

    //
    // Due to the undocumented and somewhat strange struct-return handling when
    // using ffi_raw_call(), we convert from raw to ptr array, then call via normal
    // ffi_call
    //

    ffiArgs = alloca(ctx->cif.nargs * sizeof(void *));

#ifdef USE_RAW
    tmpBuffer = alloca(ctx->rawParameterSize);
    (*env)->GetByteArrayRegion(env, paramBuffer, 0, ctx->rawParameterSize, tmpBuffer);
    for (i = 0; i < (int) ctx->cif.nargs; ++i) {
        ffiArgs[i] = (tmpBuffer + ctx->rawParamOffsets[i]);
    }
#else
    tmpBuffer = alloca(ctx->cif.nargs * PARAM_SIZE);
    (*env)->GetByteArrayRegion(env, paramBuffer, 0, ctx->cif.nargs * PARAM_SIZE, tmpBuffer);
    for (i = 0; i < (int) ctx->cif.nargs; ++i) {
        ffiArgs[i] = &tmpBuffer[i * PARAM_SIZE];
    }
#endif
    ffi_call(&ctx->cif, FFI_FN(ctx->function), retval, ffiArgs);
    SAVE_ERRNO(ctx);
    (*env)->SetByteArrayRegion(env, returnBuffer, offset, ctx->cif.rtype->size, retval);
}
示例#6
0
文件: Field.cpp 项目: ahua/java
            static PyObject *t_Field_getName(t_Field *self)
            {
                String name((jobject) NULL);

                OBJ_CALL(name = self->object.getName());
                return j2p(name);
            }
示例#7
0
/*
 * Class:     com_kenai_jffi_Foreign
 * Method:    VirtualFree
 * Signature: (JI)Z
 */
JNIEXPORT jboolean JNICALL
Java_com_kenai_jffi_Foreign_VirtualFree(JNIEnv *env, jobject self, jlong addr, jint size, jint flags)
{
    if (!VirtualFree(j2p(addr), size, flags)) {
        jffi_save_errno();
        return JNI_FALSE;
    }

    return JNI_TRUE;
}
示例#8
0
JNIEXPORT jlong JNICALL
Java_com_kenai_jffi_Foreign_dlsym(JNIEnv* env, jclass cls, jlong handle, jstring jstr)
{
    char sym[1024];
    getMultibyteString(env, sym, jstr, sizeof(sym));
#ifndef _WIN32
    dlerror(); // clear any errors
#endif
    return p2j(dl_sym(j2p(handle), sym));
}
示例#9
0
/*
 * Class:     com_kenai_jffi_Foreign
 * Method:    invokeArrayReturnStruct
 * Signature: (J[B[B)V
 */
JNIEXPORT void JNICALL
Java_com_kenai_jffi_Foreign_invokeArrayReturnStruct(JNIEnv* env, jclass self, jlong ctxAddress,
        jbyteArray paramBuffer, jbyteArray returnBuffer, jint offset)
{
    Function* ctx = (Function *) j2p(ctxAddress);
    jbyte* retval = alloca_aligned(ctx->cif.rtype->size, MIN_ALIGN);
    
    invokeArray(env, ctxAddress, paramBuffer, retval);
    (*env)->SetByteArrayRegion(env, returnBuffer, offset, ctx->cif.rtype->size, retval);
}
示例#10
0
/*
 * Class:     com_kenai_jffi_Foreign
 * Method:    mprotect
 * Signature: (JJI)I
 */
JNIEXPORT jint JNICALL
Java_com_kenai_jffi_Foreign_mprotect(JNIEnv *env, jobject self, jlong addr, jlong len, jint prot)
{
    int result = mprotect(j2p(addr), len, PROT(prot));
    if (unlikely(result != 0)) {
        jffi_save_errno();
        return -1;
    }

    return 0;
}
示例#11
0
/*
 * Class:     com_kenai_jffi_Foreign
 * Method:    VirtualAlloc
 * Signature: (JIII)J
 */
JNIEXPORT jlong JNICALL
Java_com_kenai_jffi_Foreign_VirtualAlloc(JNIEnv *env, jobject self, jlong addr, jint size, jint flags, jint prot)
{
    void* ptr = VirtualAlloc(j2p(addr), size, flags, prot);
    if (unlikely(ptr == NULL)) {
        jffi_save_errno();
        return 0;
    }

    return p2j(ptr);
}
示例#12
0
/*
 * Class:     com_kenai_jffi_Foreign
 * Method:    VirtualProtect
 * Signature: (JII)Z
 */
JNIEXPORT jboolean JNICALL
Java_com_kenai_jffi_Foreign_VirtualProtect(JNIEnv *env, jobject self, jlong addr, jint size, jint prot)
{
    DWORD oldprot;
    if (!VirtualProtect(j2p(addr), size, prot, &oldprot)) {
        jffi_save_errno();
        return JNI_FALSE;
    }

    return JNI_TRUE;
}
示例#13
0
文件: Invoke.c 项目: Flameeyes/jffi
/*
 * Class:     com_kenai_jffi_Foreign
 * Method:    invokeArrayWithObjectsReturnStruct
 * Signature: (J[BI[I[Ljava/lang/Object;[BI)V
 */
JNIEXPORT void JNICALL
Java_com_kenai_jffi_Foreign_invokeArrayWithObjectsReturnStruct(JNIEnv* env, jobject self,
       jlong ctxAddress, jbyteArray paramBuffer, jint objectCount, jintArray objectInfo,
       jobjectArray objectArray, jbyteArray returnBuffer, jint returnBufferOffset)
{
    Function* ctx = (Function *) j2p(ctxAddress);
    jbyte* retval = alloca(ctx->cif.rtype->size);
    
    invokeArrayWithObjects(env, ctxAddress, paramBuffer, objectCount, objectInfo, objectArray, retval);
    (*env)->SetByteArrayRegion(env, returnBuffer, returnBufferOffset, ctx->cif.rtype->size, retval);
}
示例#14
0
/*
 * Class:     com_kenai_jffi_Foreign
 * Method:    munmap
 * Signature: (JJ)I
 */
JNIEXPORT jint JNICALL
Java_com_kenai_jffi_Foreign_munmap(JNIEnv *env, jobject self, jlong addr, jlong len)
{
    int result = munmap(j2p(addr), len);
    if (unlikely(result != 0)) {
        jffi_save_errno();
        return -1;
    }

    return 0;
}
示例#15
0
/*
 * Class:     com_kenai_jffi_Foreign
 * Method:    freeStruct
 * Signature: (J)V
 */
JNIEXPORT void JNICALL
Java_com_kenai_jffi_Foreign_freeStruct(JNIEnv* env, jobject self, jlong handle)
{
    ffi_type* s = (ffi_type *) j2p(handle);
    
    if (s != NULL) {
        if (s->elements != NULL) {
            free(s->elements);
        }
        free(s);
    }
}
示例#16
0
/*
 * Class:     com_kenai_jffi_Foreign
 * Method:    mmap
 * Signature: (JJIIIJ)J
 */
JNIEXPORT jlong JNICALL
Java_com_kenai_jffi_Foreign_mmap(JNIEnv *env, jobject self, jlong addr, jlong len,
        jint prot, jint flags, jint fd, jlong off)
{
    caddr_t result;
    
    result = mmap(j2p(addr), len, PROT(prot), FLAGS(flags), fd, off);
    if (unlikely(result == (caddr_t) -1)) {
        jffi_save_errno();
        return -1;
    }

    return p2j(result);
}
示例#17
0
文件: Invoke.c 项目: Flameeyes/jffi
/*
 * Class:     com_kenai_jffi_Foreign
 * Method:    invokePointerParameterArray
 * Signature: (JJ[J)V
 */
JNIEXPORT void JNICALL
Java_com_kenai_jffi_Foreign_invokePointerParameterArray(JNIEnv *env, jobject self, jlong ctxAddress,
        jlong returnBuffer, jlongArray parameterArray)
{
    Function* ctx = (Function *) j2p(ctxAddress);
    int parameterCount;
    jlong* params = NULL;
    void** ffiArgs = NULL;
    int i;

    if (unlikely(ctxAddress == 0LL)) {
        throwException(env, NullPointer, "context address is null");
        return;
    }

    if (unlikely(returnBuffer == 0LL)) {
        throwException(env, NullPointer, "result buffer is null");
        return;
    }

    if (unlikely(parameterArray == NULL)) {
        throwException(env, NullPointer, "parameter array is null");
        return;
    }

    parameterCount = (*env)->GetArrayLength(env, parameterArray);
    if (parameterCount > 0) {
         params = alloca(parameterCount * sizeof(jlong));
         ffiArgs = alloca(parameterCount * sizeof(void *));
        (*env)->GetLongArrayRegion(env, parameterArray, 0, parameterCount, params);
        for (i = 0; i < parameterCount; ++i) {
            ffiArgs[i] = j2p(params[i]);
        }
    }
    
    ffi_call(&ctx->cif, FFI_FN(ctx->function), j2p(returnBuffer), ffiArgs);
}
示例#18
0
/*
 * Class:     com_kenai_jffi_Foreign
 * Method:    freeClosureMagazine
 * Signature: (J)V
 */
JNIEXPORT void JNICALL
Java_com_kenai_jffi_Foreign_freeClosureMagazine(JNIEnv *env, jobject self, jlong magAddress)
{
    Magazine* magazine = (Magazine *) j2p(magAddress);
    Closure* closure;
    int i;

    for (i = 0; i < magazine->nextclosure; ++i) {
        (*env)->DeleteGlobalRef(env, magazine->closures[i].javaObject);
    }

    free(magazine->closures);
    jffi_freePages(magazine->code, 1);
    free(magazine);
}
示例#19
0
文件: Invoke.c 项目: Flameeyes/jffi
static void
invokeArray(JNIEnv* env, jlong ctxAddress, jbyteArray paramBuffer, void* returnBuffer)
{
    Function* ctx = (Function *) j2p(ctxAddress);
    FFIValue tmpValue;
    jbyte *tmpBuffer = (jbyte *) &tmpValue;
    
    if (likely(ctx->cif.nargs > 0)) {
        tmpBuffer = alloca(ctx->cif.bytes);
        
        (*env)->GetByteArrayRegion(env, paramBuffer, 0, ctx->rawParameterSize, tmpBuffer);
    }

    ffi_raw_call(&ctx->cif, FFI_FN(ctx->function), returnBuffer, (ffi_raw *) tmpBuffer);
    SAVE_ERRNO(ctx);
}
示例#20
0
/*
 * Class:     com_kenai_jffi_Foreign
 * Method:    closureMagazineGet
 * Signature: (JLjava/lang/Object;)J
 */
JNIEXPORT jlong JNICALL
Java_com_kenai_jffi_Foreign_closureMagazineGet(JNIEnv *env, jobject self, jlong magAddress, jobject closureProxy)
{
    Magazine* magazine = (Magazine *) j2p(magAddress);
    if (magazine->nextclosure < magazine->nclosures) {
        Closure* closure = &magazine->closures[magazine->nextclosure];
        closure->javaObject = (*env)->NewGlobalRef(env, closureProxy);
        if (closure->javaObject == NULL) {
            throwException(env, IllegalArgument, "could not obtain reference to java object");
            return 0L;
        }
        
        magazine->nextclosure++;
        return p2j(closure);
    }

    return 0L;
}
示例#21
0
文件: Library.c 项目: jnr/jffi
JNIEXPORT jlong JNICALL
Java_com_kenai_jffi_Foreign_dlsym(JNIEnv* env, jclass cls, jlong handle, jstring jstr)
{
    char sym[1024];
    void* addr;

    getMultibyteString(env, sym, jstr, sizeof(sym));
#ifndef _WIN32
    dlerror(); // clear any errors
#endif
    addr = dl_sym(j2p(handle), sym);
    if (addr == NULL) {
        char errbuf[1024] = { 0 };
        dl_error(errbuf, sizeof(errbuf) - 1);
        throwException(env, UnsatisfiedLink, "%s", errbuf);
    }

    return p2j(addr);
}
示例#22
0
文件: Type.c 项目: Flameeyes/jffi
/*
 * Class:     com_kenai_jffi_Foreign
 * Method:    getTypeType
 * Signature: (J)I
 */
JNIEXPORT jint JNICALL
Java_com_kenai_jffi_Foreign_getTypeType(JNIEnv* env, jobject self, jlong handle)
{
    return ((ffi_type *) j2p(handle))->type;
}
示例#23
0
/*
 * Class:     com_googlecode_jffi_NativeLibrary
 * Method:    dlclose
 * Signature: (J)V
 */
JNIEXPORT void JNICALL
Java_com_kenai_jffi_Foreign_dlclose(JNIEnv* env, jclass cls, jlong handle)
{
    dl_close(j2p(handle));
}
示例#24
0
文件: Foreign.c 项目: abstractj/jffi
JNIEXPORT jint JNICALL
Java_com_kenai_jffi_Foreign_registerNatives(JNIEnv *env, jobject self, jclass clazz,
        jlong methods, jint nmethods)
{
    return (*env)->RegisterNatives(env, clazz, j2p(methods), nmethods);
}
示例#25
0
static void
invokeArrayWithObjects_(JNIEnv* env, jlong ctxAddress, jbyteArray paramBuffer,
        jint objectCount, jint* infoBuffer, jobject* objectBuffer, void* retval)
{
    Function* ctx = (Function *) j2p(ctxAddress);
    union { double d; long long ll; jbyte tmp[PARAM_SIZE]; } tmpStackBuffer[MAX_STACK_ARGS];
    jbyte *tmpBuffer = (jbyte *) &tmpStackBuffer[0];
#if defined(USE_RAW)
    int rawAdj = ctx->cif.rtype->type == FFI_TYPE_STRUCT ? sizeof(void *) : 0;
#else
    void* ffiStackArgs[MAX_STACK_ARGS], **ffiArgs = &ffiStackArgs[0];
#endif
    Array stackArrays[MAX_STACK_OBJECTS], *arrays = &stackArrays[0];
    StackAllocator alloc;
    unsigned int i, arrayCount = 0;

    if (ctx->cif.nargs > MAX_STACK_ARGS) {
        tmpBuffer = alloca_aligned(ctx->cif.nargs * PARAM_SIZE, MIN_ALIGN);
    }
#if defined(USE_RAW)
    (*env)->GetByteArrayRegion(env, paramBuffer, 0, ctx->rawParameterSize, tmpBuffer + rawAdj);
#else
    if (ctx->cif.nargs > MAX_STACK_ARGS) {
        ffiArgs = alloca_aligned(ctx->cif.nargs * sizeof(void *), MIN_ALIGN);
    }
    for (i = 0; i < ctx->cif.nargs; ++i) {
        ffiArgs[i] = &tmpBuffer[i * PARAM_SIZE];
    }
    (*env)->GetByteArrayRegion(env, paramBuffer, 0, ctx->cif.nargs * PARAM_SIZE, tmpBuffer);
#endif
    
    if (objectCount > MAX_STACK_OBJECTS) {
        arrays = alloca_aligned(objectCount * sizeof(Array), MIN_ALIGN);
    }
    initStackAllocator(&alloc);
    for (i = 0; i < (unsigned int) objectCount; ++i) {
        int type = infoBuffer[i * 3];
        jsize offset = infoBuffer[(i * 3) + 1];
        jsize length = infoBuffer[(i * 3) + 2];
        jobject object = objectBuffer[i];
        int idx = (type & com_kenai_jffi_ObjectBuffer_INDEX_MASK) >> com_kenai_jffi_ObjectBuffer_INDEX_SHIFT;
        void* ptr;

        switch (type & com_kenai_jffi_ObjectBuffer_TYPE_MASK & ~com_kenai_jffi_ObjectBuffer_PRIM_MASK) {
            case com_kenai_jffi_ObjectBuffer_ARRAY:
                ptr = jffi_getArray(env, object, offset, length, type, &alloc, &arrays[arrayCount]);
                if (ptr == NULL) {
                    throwException(env, NullPointer, "Could not allocate array");
                    goto cleanup;
                }
                ++arrayCount;
                break;
            case com_kenai_jffi_ObjectBuffer_BUFFER:
                ptr = (*env)->GetDirectBufferAddress(env, object);
                if (ptr == NULL) {
                    throwException(env, NullPointer, "Could not get direct Buffer address");
                    goto cleanup;
                }
                ptr = ((char *) ptr + offset);
                break;
            default:
                throwException(env, IllegalArgument, "Unsupported object type: %#x", 
                        type & com_kenai_jffi_ObjectBuffer_TYPE_MASK);
                goto cleanup;
        }

#if defined(USE_RAW)
        *((void **)(tmpBuffer + rawAdj + ctx->rawParamOffsets[idx])) = ptr;
#else
        if (ctx->cif.arg_types[idx]->type == FFI_TYPE_STRUCT) {
            ffiArgs[idx] = ptr;
        } else {
            *((void **) ffiArgs[idx]) = ptr;
        }
#endif
    }
#if defined(USE_RAW)
    // For struct return values, we need to push a return value address on the parameter stack
    if (ctx->cif.rtype->type == FFI_TYPE_STRUCT) {
        *(void **) tmpBuffer = retval;
    }
    ffi_raw_call(&ctx->cif, FFI_FN(ctx->function), retval, (ffi_raw *) tmpBuffer);
#else
    ffi_call(&ctx->cif, FFI_FN(ctx->function), retval, ffiArgs);
#endif
    set_last_error(errno);
cleanup:
    /* Release any array backing memory */
    for (i = 0; i < arrayCount; ++i) {
        if (!arrays[i].stack || arrays[i].mode != JNI_ABORT) {
            //printf("releasing array=%p\n", arrays[i].result);
            (*arrays[i].release)(env, &arrays[i]);
        }
    }
}
示例#26
0
void front_or_back(char **argv, int fg_or_not) {
	int jid = 0;
	int fg_run = fg_or_not;
	pid_t pid = 0;
	pid_t j2pid = 0;

	if (fbg_argv_ok(argv, &pid, &jid)) {
		if (pid) {
			if (selectjob(pid)) {
				child_block();
				restart_job(pid);
				if (fg_run) {
					forepid = pid;
					setpgid(pid, shellpid);
					child_unblock();
					printf("bg ready to fg\n");
					while (1) 
						sleep(50);
					printf("u never see me\n");
					return;
				}
				else {
					child_unblock();
					return;
				}
			}
			else {
				fprintf(stderr, "%d: No such process\n", pid);
				return;
			}
		}
		else {   
			j2pid = j2p(jid);
			if (selectjob(j2pid)) {
				child_block();
				restart_job(j2pid);
				if (fg_run) {
					forepid = j2pid;
					setpgid(j2pid, shellpid);
					child_unblock();
					printf("bg ready to fg\n");
					while (1)
						sleep(50);
					printf("u never see me\n");
					return;
				}
				else {
					child_unblock();
					return;
				}
			}
			else {
				fprintf(stderr, "%d: No such process\n", j2p(jid));
				return;
			}
		}
	}
	else
		fprintf(stderr, "usage: %s <%%jid> or %s <pid>\n",
				argv[0], argv[0]);
	return;
}
示例#27
0
JNIEXPORT jlong JNICALL
Java_com_kenai_jffi_Foreign_newClosureMagazine(JNIEnv *env, jobject self, jlong ctxAddress, jobject closureMethod,
    jboolean callWithPrimitiveParameters)
{
    CallContext* ctx = (CallContext *) j2p(ctxAddress);
    Closure* list = NULL;
    Magazine* magazine = NULL;
    caddr_t code = NULL;
    char errmsg[256];
    int i;
    int trampolineSize, pageSize, nclosures;

    trampolineSize = roundup(sizeof(ffi_closure), 8);
    pageSize = jffi_getPageSize();
    nclosures = pageSize / trampolineSize;

    magazine = calloc(1, sizeof(*magazine));
    list = calloc(nclosures, sizeof(*list));
    code = jffi_allocatePages(1);

    if (magazine == NULL || list == NULL || code == NULL) {
        snprintf(errmsg, sizeof(errmsg), "failed to allocate a page. errno=%d (%s)", errno, strerror(errno));
        goto error;
    }
    
    // Thread all the closure handles onto a list, and init each one
    for (i = 0; i < nclosures; ++i) {
        Closure* closure = &list[i];
        closure->magazine = magazine;
        closure->code = (code + (i * trampolineSize));

        if (!closure_prep(&ctx->cif, closure->code, closure, errmsg, sizeof(errmsg))) {
            goto error;
        }
    }
    

    if (!jffi_makePagesExecutable(code, 1)) {
        snprintf(errmsg, sizeof(errmsg), "failed to make page executable. errno=%d (%s)", errno, strerror(errno));
        goto error;
    }

    magazine->methodID = (*env)->FromReflectedMethod(env, closureMethod);
    if (magazine->methodID == NULL) {
        throwException(env, IllegalArgument, "could not obtain reference to closure method");
        goto error;
    }

    /* Track the allocated page + Closure memory area */
    magazine->closures = list;
    magazine->nextclosure = 0;
    magazine->nclosures = nclosures;
    magazine->code = code;
    magazine->callWithPrimitiveParameters = callWithPrimitiveParameters;
    (*env)->GetJavaVM(env, &magazine->jvm);

    return p2j(magazine);

error:
    free(list);
    free(magazine);
    if (code != NULL) {
        jffi_freePages(code, 1);
    }
    throwException(env, Runtime, errmsg);
    return 0L;
}
示例#28
0
文件: Invoke.c 项目: Flameeyes/jffi
static void
invokeArrayWithObjects_(JNIEnv* env, jlong ctxAddress, jbyteArray paramBuffer,
        jint objectCount, jint* infoBuffer, jobject* objectBuffer, void* retval)
{
    Function* ctx = (Function *) j2p(ctxAddress);
    jbyte *tmpBuffer = NULL;
    void **ffiArgs = NULL;
    Array *arrays = NULL;
    unsigned int i, arrayCount = 0, paramBytes = 0;

    arrays = alloca(objectCount * sizeof(Array));

#if defined(USE_RAW)
    paramBytes = ctx->rawParameterSize;
#else
    paramBytes = ctx->cif.nargs * PARAM_SIZE;
#endif

    tmpBuffer = alloca(paramBytes);
    (*env)->GetByteArrayRegion(env, paramBuffer, 0, paramBytes, tmpBuffer);

#ifndef USE_RAW
    ffiArgs = alloca(ctx->cif.nargs * sizeof(void *));
    
    for (i = 0; i < (unsigned int) ctx->cif.nargs; ++i) {
        ffiArgs[i] = &tmpBuffer[i * PARAM_SIZE];
    }
#endif    

    
    for (i = 0; i < (unsigned int) objectCount; ++i) {
        int type = infoBuffer[i * 3];
        jsize offset = infoBuffer[(i * 3) + 1];
        jsize length = infoBuffer[(i * 3) + 2];
        jobject object = objectBuffer[i];
        int idx = (type & com_kenai_jffi_ObjectBuffer_INDEX_MASK) >> com_kenai_jffi_ObjectBuffer_INDEX_SHIFT;
        void* ptr;

        switch (type & com_kenai_jffi_ObjectBuffer_TYPE_MASK & ~com_kenai_jffi_ObjectBuffer_PRIM_MASK) {
            case com_kenai_jffi_ObjectBuffer_ARRAY:
                if (unlikely(object == NULL)) {
                    throwException(env, NullPointer, "null object for parameter %d", idx);
                    goto cleanup;
                
                } else if (unlikely((type & com_kenai_jffi_ObjectBuffer_PINNED) != 0)) {

                    ptr = jffi_getArrayCritical(env, object, offset, length, type, &arrays[arrayCount]);
                    if (unlikely(ptr == NULL)) {
                        goto cleanup;
                    }
                } else if (true && likely(length < MAX_STACK_ARRAY)) {

                    ptr = alloca(jffi_arraySize(length + 1, type));
                    if (unlikely(jffi_getArrayBuffer(env, object, offset, length, type,
                        &arrays[arrayCount], ptr) == NULL)) {
                        goto cleanup;
                    }

                } else {
                    ptr = jffi_getArrayHeap(env, object, offset, length, type, &arrays[arrayCount]);
                    if (unlikely(ptr == NULL)) {
                        goto cleanup;
                    }
                }
                
                ++arrayCount;
                break;

            case com_kenai_jffi_ObjectBuffer_BUFFER:
                ptr = (*env)->GetDirectBufferAddress(env, object);
                if (unlikely(ptr == NULL)) {
                    throwException(env, NullPointer, "Could not get direct Buffer address");
                    goto cleanup;
                }
                ptr = ((char *) ptr + offset);
                break;

            case com_kenai_jffi_ObjectBuffer_JNI:
                switch (type & com_kenai_jffi_ObjectBuffer_TYPE_MASK) {
                    case com_kenai_jffi_ObjectBuffer_JNIENV:
                        ptr = env;
                        break;
                    case com_kenai_jffi_ObjectBuffer_JNIOBJECT:
                        ptr = (void *) object;
                        break;
                    default:
                        throwException(env, IllegalArgument, "Unsupported object type: %#x",
                            type & com_kenai_jffi_ObjectBuffer_TYPE_MASK);
                        goto cleanup;
                }
                
                break;
            default:
                throwException(env, IllegalArgument, "Unsupported object type: %#x", 
                        type & com_kenai_jffi_ObjectBuffer_TYPE_MASK);
                goto cleanup;
        }

#if defined(USE_RAW)
        *((void **)(tmpBuffer + ctx->rawParamOffsets[idx])) = ptr;
#else
        if (unlikely(ctx->cif.arg_types[idx]->type == FFI_TYPE_STRUCT)) {
            ffiArgs[idx] = ptr;
        } else {
            *((void **) ffiArgs[idx]) = ptr;
        }
#endif
    }
#if defined(USE_RAW)
    //
    // Special case for struct return values - unroll into a ptr array and
    // use ffi_call, since ffi_raw_call with struct return values is undocumented.
    //
    if (unlikely(ctx->cif.rtype->type == FFI_TYPE_STRUCT)) {
        ffiArgs = alloca(ctx->cif.nargs * sizeof(void *));
        for (i = 0; i < ctx->cif.nargs; ++i) {
            ffiArgs[i] = (tmpBuffer + ctx->rawParamOffsets[i]);
        }
        ffi_call(&ctx->cif, FFI_FN(ctx->function), retval, ffiArgs);
    } else {
        ffi_raw_call(&ctx->cif, FFI_FN(ctx->function), retval, (ffi_raw *) tmpBuffer);
    }
#else
    ffi_call(&ctx->cif, FFI_FN(ctx->function), retval, ffiArgs);
#endif
    SAVE_ERRNO(ctx);
cleanup:
    /* Release any array backing memory */
    for (i = 0; i < arrayCount; ++i) {
        if (arrays[i].release != NULL) {
            //printf("releasing array=%p\n", arrays[i].elems);
            (*arrays[i].release)(env, &arrays[i]);
        }
    }
}
示例#29
0
/*
 * Class:     com_kenai_jffi_Foreign
 * Method:    newStruct
 * Signature: ([J)J
 */
JNIEXPORT jlong JNICALL
Java_com_kenai_jffi_Foreign_newStruct(JNIEnv* env, jobject self, jlongArray typeArray, jboolean isUnion)
{
    ffi_type* s = NULL;
    int fieldCount;
    jlong* fieldTypes;
    int i;

    if (typeArray == NULL) {
        throwException(env, NullPointer, "types array cannot be null");
        return 0L;
    }

    fieldCount = (*env)->GetArrayLength(env, typeArray);
    if (fieldCount < 1) {
        throwException(env, IllegalArgument, "No fields specified");
        return 0L;
    }

    s = calloc(1, sizeof(*s));
    if (s == NULL) {
        return 0L;
    }

    //
    // Need to terminate the list of field types with a NULL, so allocate 1 extra
    //
    s->elements = calloc(fieldCount + 1, sizeof(ffi_type *));
    if (s->elements == NULL) {
        goto error;
    }

    // Copy out all the field descriptors
    fieldTypes = alloca(fieldCount * sizeof(jlong));
    (*env)->GetLongArrayRegion(env, typeArray, 0, fieldCount, fieldTypes);
    
    s->type = FFI_TYPE_STRUCT;
    s->size = 0;
    s->alignment = 0;

    for (i = 0; i < fieldCount; ++i) {
        ffi_type* elem = (ffi_type *) j2p(fieldTypes[i]);

        if (elem == NULL) {
            throwException(env, IllegalArgument, "Type for field %d is NULL", i);
            goto error;
        }
        if (elem->size == 0) {
            throwException(env, IllegalArgument, "Type for field %d has size 0", i);
            goto error;
        }

        s->elements[i] = elem;
        if (!isUnion) {
            s->size = ALIGN(s->size, elem->alignment) + elem->size;
        } else {
            s->size = MAX(s->size, elem->size);
        }
        s->alignment = MAX(s->alignment, elem->alignment);
        //printf("s->size=%d s->alignment=%d\n", s->size, s->alignment);
    }
    if (s->size == 0) {
        throwException(env, Runtime, "Struct size is zero");
        goto error;
    }
    
    // Include tail padding
    s->size = ALIGN(s->size, s->alignment);
    return p2j(s);
    
error:
    if (s != NULL) {
        if (s->elements != NULL) {
            free(s->elements);
        }
        free(s);
    }
    return 0L;
}