1 /* 2 * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 #include "jdk_internal_foreign_abi_fallback_LibFallback.h" 27 28 #include <ffi.h> 29 30 #include <errno.h> 31 #include <stdint.h> 32 #include <wchar.h> 33 #ifdef _WIN64 34 #include <Windows.h> 35 #include <Winsock2.h> 36 #endif 37 38 #include "jlong.h" 39 40 static JavaVM* VM; 41 static jclass LibFallback_class; 42 static jmethodID LibFallback_doUpcall_ID; 43 static const char* LibFallback_doUpcall_sig = "(JJLjava/lang/invoke/MethodHandle;)V"; 44 45 JNIEXPORT void JNICALL 46 Java_jdk_internal_foreign_abi_fallback_LibFallback_init(JNIEnv* env, jclass cls) { 47 (*env)->GetJavaVM(env, &VM); 48 LibFallback_class = (*env)->FindClass(env, "jdk/internal/foreign/abi/fallback/LibFallback"); 49 LibFallback_doUpcall_ID = (*env)->GetStaticMethodID(env, 50 LibFallback_class, "doUpcall", LibFallback_doUpcall_sig); 51 } 52 53 JNIEXPORT jlong JNICALL 54 Java_jdk_internal_foreign_abi_fallback_LibFallback_sizeofCif(JNIEnv* env, jclass cls) { 55 return sizeof(ffi_cif); 56 } 57 58 JNIEXPORT jint JNICALL 59 Java_jdk_internal_foreign_abi_fallback_LibFallback_ffi_1prep_1cif(JNIEnv* env, jclass cls, jlong cif, jint abi, jint nargs, jlong rtype, jlong atypes) { 60 return ffi_prep_cif(jlong_to_ptr(cif), (ffi_abi) abi, (unsigned int) nargs, jlong_to_ptr(rtype), jlong_to_ptr(atypes)); 61 } 62 JNIEXPORT jint JNICALL 63 Java_jdk_internal_foreign_abi_fallback_LibFallback_ffi_1prep_1cif_1var(JNIEnv* env, jclass cls, jlong cif, jint abi, jint nfixedargs, jint ntotalargs, jlong rtype, jlong atypes) { 64 return ffi_prep_cif_var(jlong_to_ptr(cif), (ffi_abi) abi, (unsigned int) nfixedargs, (unsigned int) ntotalargs, jlong_to_ptr(rtype), jlong_to_ptr(atypes)); 65 } 66 JNIEXPORT jint JNICALL 67 Java_jdk_internal_foreign_abi_fallback_LibFallback_ffi_1get_1struct_1offsets(JNIEnv* env, jclass cls, jint abi, jlong type, jlong offsets) { 68 return ffi_get_struct_offsets((ffi_abi) abi, jlong_to_ptr(type), jlong_to_ptr(offsets)); 69 } 70 71 static void do_capture_state(int32_t* value_ptr, int captured_state_mask) { 72 // keep in synch with jdk.internal.foreign.abi.CapturableState 73 enum PreservableValues { 74 NONE = 0, 75 GET_LAST_ERROR = 1, 76 WSA_GET_LAST_ERROR = 1 << 1, 77 ERRNO = 1 << 2 78 }; 79 #ifdef _WIN64 80 if (captured_state_mask & GET_LAST_ERROR) { 81 *value_ptr = GetLastError(); 82 } 83 value_ptr++; 84 if (captured_state_mask & WSA_GET_LAST_ERROR) { 85 *value_ptr = WSAGetLastError(); 86 } 87 value_ptr++; 88 #endif 89 if (captured_state_mask & ERRNO) { 90 *value_ptr = errno; 91 } 92 } 93 94 JNIEXPORT void JNICALL 95 Java_jdk_internal_foreign_abi_fallback_LibFallback_doDowncall(JNIEnv* env, jclass cls, jlong cif, jlong fn, jlong rvalue, jlong avalues, jlong jcaptured_state, jint captured_state_mask) { 96 ffi_call(jlong_to_ptr(cif), jlong_to_ptr(fn), jlong_to_ptr(rvalue), jlong_to_ptr(avalues)); 97 98 if (captured_state_mask != 0) { 99 int32_t* captured_state = jlong_to_ptr(jcaptured_state); 100 do_capture_state(captured_state, captured_state_mask); 101 } 102 } 103 104 static void do_upcall(ffi_cif* cif, void* ret, void** args, void* user_data) { 105 // attach thread 106 JNIEnv* env; 107 jint result = (*VM)->AttachCurrentThreadAsDaemon(VM, (void**) &env, NULL); 108 109 // call into doUpcall in LibFallback 110 jobject upcall_data = (jobject) user_data; 111 (*env)->CallStaticVoidMethod(env, LibFallback_class, LibFallback_doUpcall_ID, 112 ptr_to_jlong(ret), ptr_to_jlong(args), upcall_data); 113 114 // always detach for now 115 (*VM)->DetachCurrentThread(VM); 116 } 117 118 static void free_closure(JNIEnv* env, void* closure, jobject upcall_data) { 119 ffi_closure_free(closure); 120 (*env)->DeleteGlobalRef(env, upcall_data); 121 } 122 123 JNIEXPORT jint JNICALL 124 Java_jdk_internal_foreign_abi_fallback_LibFallback_createClosure(JNIEnv* env, jclass cls, jlong cif, jobject upcall_data, jlongArray jptrs) { 125 void* code; 126 void* closure = ffi_closure_alloc(sizeof(ffi_closure), &code); 127 128 jobject global_upcall_data = (*env)->NewGlobalRef(env, upcall_data); 129 130 ffi_status status = ffi_prep_closure_loc(closure, jlong_to_ptr(cif), &do_upcall, (void*) global_upcall_data, code); 131 132 if (status != FFI_OK) { 133 free_closure(env,closure, global_upcall_data); 134 return status; 135 } 136 137 jlong* ptrs = (*env)->GetLongArrayElements(env, jptrs, NULL); 138 ptrs[0] = ptr_to_jlong(closure); 139 ptrs[1] = ptr_to_jlong(code); 140 ptrs[2] = ptr_to_jlong(global_upcall_data); 141 (*env)->ReleaseLongArrayElements(env, jptrs, ptrs, JNI_COMMIT); 142 143 return status; 144 } 145 146 JNIEXPORT void JNICALL 147 Java_jdk_internal_foreign_abi_fallback_LibFallback_freeClosure(JNIEnv* env, jclass cls, jlong closure, jlong upcall_data) { 148 free_closure(env, jlong_to_ptr(closure), jlong_to_ptr(upcall_data)); 149 } 150 151 JNIEXPORT jint JNICALL 152 Java_jdk_internal_foreign_abi_fallback_LibFallback_ffi_1default_1abi(JNIEnv* env, jclass cls) { 153 return (jint) FFI_DEFAULT_ABI; 154 } 155 156 JNIEXPORT jshort JNICALL 157 Java_jdk_internal_foreign_abi_fallback_LibFallback_ffi_1type_1struct(JNIEnv* env, jclass cls) { 158 return (jshort) FFI_TYPE_STRUCT; 159 } 160 161 JNIEXPORT jlong JNICALL 162 Java_jdk_internal_foreign_abi_fallback_LibFallback_ffi_1type_1void(JNIEnv* env, jclass cls) { 163 return ptr_to_jlong(&ffi_type_void); 164 } 165 166 JNIEXPORT jlong JNICALL 167 Java_jdk_internal_foreign_abi_fallback_LibFallback_ffi_1type_1uint8(JNIEnv* env, jclass cls) { 168 return ptr_to_jlong(&ffi_type_uint8); 169 } 170 JNIEXPORT jlong JNICALL 171 Java_jdk_internal_foreign_abi_fallback_LibFallback_ffi_1type_1sint8(JNIEnv* env, jclass cls) { 172 return ptr_to_jlong(&ffi_type_sint8); 173 } 174 JNIEXPORT jlong JNICALL 175 Java_jdk_internal_foreign_abi_fallback_LibFallback_ffi_1type_1uint16(JNIEnv* env, jclass cls) { 176 return ptr_to_jlong(&ffi_type_uint16); 177 } 178 JNIEXPORT jlong JNICALL 179 Java_jdk_internal_foreign_abi_fallback_LibFallback_ffi_1type_1sint16(JNIEnv* env, jclass cls) { 180 return ptr_to_jlong(&ffi_type_sint16); 181 } 182 JNIEXPORT jlong JNICALL 183 Java_jdk_internal_foreign_abi_fallback_LibFallback_ffi_1type_1uint32(JNIEnv* env, jclass cls) { 184 return ptr_to_jlong(&ffi_type_uint32); 185 } 186 JNIEXPORT jlong JNICALL 187 Java_jdk_internal_foreign_abi_fallback_LibFallback_ffi_1type_1sint32(JNIEnv* env, jclass cls) { 188 return ptr_to_jlong(&ffi_type_sint32); 189 } 190 JNIEXPORT jlong JNICALL 191 Java_jdk_internal_foreign_abi_fallback_LibFallback_ffi_1type_1uint64(JNIEnv* env, jclass cls) { 192 return ptr_to_jlong(&ffi_type_uint64); 193 } 194 JNIEXPORT jlong JNICALL 195 Java_jdk_internal_foreign_abi_fallback_LibFallback_ffi_1type_1sint64(JNIEnv* env, jclass cls) { 196 return ptr_to_jlong(&ffi_type_sint64); 197 } 198 JNIEXPORT jlong JNICALL 199 Java_jdk_internal_foreign_abi_fallback_LibFallback_ffi_1type_1float(JNIEnv* env, jclass cls) { 200 return ptr_to_jlong(&ffi_type_float); 201 } 202 JNIEXPORT jlong JNICALL 203 Java_jdk_internal_foreign_abi_fallback_LibFallback_ffi_1type_1double(JNIEnv* env, jclass cls) { 204 return ptr_to_jlong(&ffi_type_double); 205 } 206 JNIEXPORT jlong JNICALL 207 Java_jdk_internal_foreign_abi_fallback_LibFallback_ffi_1type_1pointer(JNIEnv* env, jclass cls) { 208 return ptr_to_jlong(&ffi_type_pointer); 209 } 210 211 JNIEXPORT jint JNICALL 212 Java_jdk_internal_foreign_abi_fallback_LibFallback_ffi_1sizeof_1short(JNIEnv* env, jclass cls) { 213 return sizeof(short); 214 } 215 216 JNIEXPORT jint JNICALL 217 Java_jdk_internal_foreign_abi_fallback_LibFallback_ffi_1sizeof_1int(JNIEnv* env, jclass cls) { 218 return sizeof(int); 219 } 220 221 JNIEXPORT jint JNICALL 222 Java_jdk_internal_foreign_abi_fallback_LibFallback_ffi_1sizeof_1long(JNIEnv* env, jclass cls) { 223 return sizeof(long); 224 } 225 226 JNIEXPORT jint JNICALL 227 Java_jdk_internal_foreign_abi_fallback_LibFallback_ffi_1sizeof_1wchar(JNIEnv* env, jclass cls) { 228 return sizeof(wchar_t); 229 }