Exemplo n.º 1
0
/*
 * Class:     com_kenai_jffi_Foreign
 * Method:    dlopen
 * Signature: (Ljava/lang/String;I)J
 */
JNIEXPORT jlong JNICALL
Java_com_kenai_jffi_Foreign_dlopen(JNIEnv* env, jobject self, jstring jPath, jint jFlags)
{
#ifdef _WIN32
    wchar_t path[PATH_MAX];
    getWideString(env, path, jstr, sizeof(path) / sizeof(path[0]));
    return p2j(LoadLibraryExW(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH));
#else
    char path_[PATH_MAX];
    const char* path = NULL; // Handle dlopen(NULL, flags);
    int flags = 0;
#define F(x) (jFlags & com_kenai_jffi_Foreign_RTLD_##x) != 0 ? RTLD_##x : 0;
    flags |= F(LAZY);
    flags |= F(GLOBAL);
    flags |= F(LOCAL);
    flags |= F(NOW);
#undef F

#ifdef _AIX
    flags |= RTLD_MEMBER; //  Needed for AIX
#endif
    
    if (jPath != NULL) {
        path = path_;
        getMultibyteString(env, path_, jPath, sizeof(path_));
    }
    return p2j(dl_open(path, flags));
#endif
}
Exemplo n.º 2
0
JNIEXPORT jlong JNICALL
Java_com_kenai_jffi_Foreign_getJavaVM(JNIEnv *env, jobject self)
{
    JavaVM* vm;
    (*env)->GetJavaVM(env, &vm);
    return p2j(vm);
}
Exemplo n.º 3
0
Arquivo: Library.c Projeto: jnr/jffi
/*
 * Class:     com_kenai_jffi_Foreign
 * Method:    dlopen
 * Signature: (Ljava/lang/String;I)J
 */
JNIEXPORT jlong JNICALL
Java_com_kenai_jffi_Foreign_dlopen(JNIEnv* env, jobject self, jstring jPath, jint jFlags)
{
#ifdef _WIN32
    if (jPath == NULL) {
        return p2j(GetModuleHandle(NULL));
    } else {
        wchar_t path[PATH_MAX];
        DWORD dwFlags;
        getWideString(env, path, jPath, sizeof(path) / sizeof(path[0]));
        dwFlags = PathIsRelativeW(path) ? 0 : LOAD_WITH_ALTERED_SEARCH_PATH;
        return p2j(LoadLibraryExW(path, NULL, dwFlags));
    }
#else
    char path_[PATH_MAX];
    const char* path = NULL; // Handle dlopen(NULL, flags);
    void* handle = NULL;
    int flags = 0;
#define F(x) (jFlags & com_kenai_jffi_Foreign_RTLD_##x) != 0 ? RTLD_##x : 0;
    flags |= F(LAZY);
    flags |= F(GLOBAL);
    flags |= F(LOCAL);
    flags |= F(NOW);
#undef F

#ifdef _AIX
    flags |= RTLD_MEMBER; //  Needed for AIX
#endif
    
    if (jPath != NULL) {
        path = path_;
        getMultibyteString(env, path_, jPath, sizeof(path_));
    }

    handle = dl_open(path, flags);
    if (handle == NULL) {
        char errbuf[1024] = { 0 };
        dl_error(errbuf, sizeof(errbuf) - 1);
        throwException(env, UnsatisfiedLink, "%s", errbuf);
    }
    
    return p2j(handle);
#endif
}
Exemplo n.º 4
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));
}
Exemplo n.º 5
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);
}
Exemplo n.º 6
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);
}
Exemplo n.º 7
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;
}
Exemplo n.º 8
0
Arquivo: Library.c Projeto: 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);
}
Exemplo n.º 9
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;
}
Exemplo n.º 10
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;
}
Exemplo n.º 11
0
static void
closure_invoke(ffi_cif* cif, void* retval, void** parameters, void* user_data)
{
    Closure* closure = (Closure *) user_data;
    
    JNIEnv* env;
    int i;
    bool detach;
#if FAULT_PROTECT_ENABLED
    ThreadData* td = thread_data_get();
    FaultData* fdp;
#endif

    closure_begin(closure, &env, &detach);
#if FAULT_PROTECT_ENABLED
    fdp = td->fault_data;
    td->fault_data = NULL;
#endif

    if (closure->magazine->callWithPrimitiveParameters) {
        // allocate one more than the parameter count (for the struct return value)
        jvalue* jparams = alloca((cif->nargs + 1) * sizeof(jvalue));

        for (i = 0; i < (int) cif->nargs; i++) {
            jvalue* vp = &jparams[i];

            vp->j = 0LL; // zero out any bits not filled below
            switch (cif->arg_types[i]->type) {
                case FFI_TYPE_SINT8:
                case FFI_TYPE_UINT8:
                    vp->b = *(jbyte *) parameters[i];
                    break;

                case FFI_TYPE_SINT16:
                case FFI_TYPE_UINT16:
                    vp->s = *(jshort *) parameters[i];
                    break;

                case FFI_TYPE_SINT32:
                case FFI_TYPE_UINT32:
                case FFI_TYPE_INT:
                    vp->i = *(jint *) parameters[i];
                    break;

                case FFI_TYPE_SINT64:
                case FFI_TYPE_UINT64:
                    vp->j = *(jlong *) parameters[i];
                    break;

                case FFI_TYPE_FLOAT:
                    vp->i = *(jfloat *) parameters[i];
                    break;

                case FFI_TYPE_DOUBLE:
                    vp->i = *(jdouble *) parameters[i];
                    break;

                case FFI_TYPE_POINTER:
                    if (cif->arg_types[i]->size == 4) {
                        vp->i = (uintptr_t) *(void **) parameters[i];
                    } else {
                        vp->j = p2j(*(void **) parameters[i]);
                    }
                    break;

                case FFI_TYPE_STRUCT:
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
                case FFI_TYPE_LONGDOUBLE:
#endif
                    vp->j = p2j(parameters[i]);
                    break;

                default:
                    memset(vp, 0, sizeof(*vp));
                    break;

            }
        }

        switch (cif->rtype->type) {
            case FFI_TYPE_VOID:
                (*env)->CallVoidMethodA(env, closure->javaObject, closure->magazine->methodID, jparams);
                *((ffi_sarg *) retval) = 0;
                break;

            case FFI_TYPE_SINT8:
                *((ffi_sarg *) retval) = (*env)->CallByteMethodA(env, closure->javaObject, closure->magazine->methodID, jparams);
                break;

            case FFI_TYPE_SINT16:
                *((ffi_sarg *) retval) = (*env)->CallShortMethodA(env, closure->javaObject, closure->magazine->methodID, jparams);
                break;

            case FFI_TYPE_SINT32:
            case FFI_TYPE_INT:
                *((ffi_sarg *) retval) = (*env)->CallIntMethodA(env, closure->javaObject, closure->magazine->methodID, jparams);
                break;

            case FFI_TYPE_UINT8:
                *((ffi_arg *) retval) = (*env)->CallByteMethodA(env, closure->javaObject, closure->magazine->methodID, jparams);
                break;

            case FFI_TYPE_UINT16:
                *((ffi_arg *) retval) = (*env)->CallShortMethodA(env, closure->javaObject, closure->magazine->methodID, jparams);
                break;

            case FFI_TYPE_UINT32:
                *((ffi_arg *) retval) = (*env)->CallIntMethodA(env, closure->javaObject, closure->magazine->methodID, jparams);
                break;

            case FFI_TYPE_SINT64:
                *((int64_t *) retval) = (*env)->CallLongMethodA(env, closure->javaObject, closure->magazine->methodID, jparams);
                break;

            case FFI_TYPE_UINT64:
                *((uint64_t *) retval) = (*env)->CallLongMethodA(env, closure->javaObject, closure->magazine->methodID, jparams);
                break;

            case FFI_TYPE_POINTER:
                if (cif->rtype->size == 4) {
                    *((ffi_arg *) retval) = (*env)->CallIntMethodA(env, closure->javaObject, closure->magazine->methodID, jparams);
                } else {
                    *((ffi_arg *) retval) = (*env)->CallLongMethodA(env, closure->javaObject, closure->magazine->methodID, jparams);
                }
                break;

            case FFI_TYPE_FLOAT:
                *((float *) retval) = (*env)->CallFloatMethodA(env, closure->javaObject, closure->magazine->methodID, jparams);
                break;

            case FFI_TYPE_DOUBLE:
                *((double *) retval) = (*env)->CallDoubleMethodA(env, closure->javaObject, closure->magazine->methodID, jparams);
                break;

            case FFI_TYPE_STRUCT:
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
                case FFI_TYPE_LONGDOUBLE:
#endif
                // stuff the retval in as the last parameter passed to the java method
                jparams[cif->nargs].j = p2j(retval);
                (*env)->CallVoidMethodA(env, closure->javaObject, closure->magazine->methodID, jparams);
                break;

            default:
                memset(retval, 0, cif->rtype->size);
        }

    } else {
        jvalue jparams[2];
        jparams[0].j = p2j(retval);
        jparams[1].j = p2j(parameters);
        //
        // Do the actual invoke - the java code will unmarshal the arguments
        //
        (*env)->CallVoidMethodA(env, closure->javaObject, closure->magazine->methodID, jparams);
    }


    if ((*env)->ExceptionCheck(env)) {
        memset(retval, 0, cif->rtype->size);
    }

#if FAULT_PROTECT_ENABLED
    td->fault_data = fdp;
#endif
    closure_end(closure, env, detach);
}
Exemplo n.º 12
0
/*
 * Class:     com_kenai_jffi_Foreign
 * Method:    lookupType
 * Signature: (I)J
 */
JNIEXPORT jlong JNICALL
Java_com_kenai_jffi_Foreign_lookupBuiltinType(JNIEnv* env, jobject self, jint type)
{
    return p2j(typeToFFI(type));
}