X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=java_strings.py;h=15c3ac4783ad222aef4647d40fcf1ebb6bec7204;hb=0d48e557e83ef085cc92c2de63b9c81c061ce78c;hp=ed9381c4f42646e6057634408244ae8d4512692f;hpb=410a782fb7c7d3815a1b04be1d15a339dd5f2d03;p=ldk-java diff --git a/java_strings.py b/java_strings.py index ed9381c4..15c3ac47 100644 --- a/java_strings.py +++ b/java_strings.py @@ -18,12 +18,13 @@ class Consts: ) self.to_hu_conv_templates = dict( - ptr = '{human_type} {var_name}_hu_conv = new {human_type}(null, {var_name});', - default = '{human_type} {var_name}_hu_conv = new {human_type}(null, {var_name});' + ptr = '{human_type} {var_name}_hu_conv = null; if ({var_name} < 0 || {var_name} > 4096) { {var_name}_hu_conv = new {human_type}(null, {var_name}); }', + default = '{human_type} {var_name}_hu_conv = null; if ({var_name} < 0 || {var_name} > 4096) { {var_name}_hu_conv = new {human_type}(null, {var_name}); }' ) self.bindings_header = """package org.ldk.impl; import org.ldk.enums.*; +import org.ldk.impl.version; import java.io.File; import java.io.InputStream; import java.io.IOException; @@ -44,7 +45,7 @@ public class bindings { try { // Try to load natively first, this works on Android and in testing. System.loadLibrary(\"lightningjni\"); - } catch (UnsatisfiedLinkError _ignored) { + } catch (UnsatisfiedLinkError system_load_err) { // Otherwise try to load from the library jar. File tmpdir = new File(System.getProperty("java.io.tmpdir"), "ldk-java-nativelib"); tmpdir.mkdir(); // If it fails to create, assume it was there already @@ -55,13 +56,16 @@ public class bindings { Path libpath = new File(tmpdir.toPath().toString(), "liblightningjni.so").toPath(); Files.copy(is, libpath, StandardCopyOption.REPLACE_EXISTING); Runtime.getRuntime().load(libpath.toString()); - } catch (IOException e) { + } catch (Exception e) { + System.err.println("Failed to load LDK native library."); + System.err.println("System LDK native library load failed with: " + system_load_err); + System.err.println("Resource-based LDK native library load failed with: " + e); throw new IllegalArgumentException(e); } } init(java.lang.Enum.class, VecOrSliceDef.class); init_class_cache(); - if (!get_lib_version_string().equals(get_ldk_java_bindings_version())) + if (!get_lib_version_string().equals(version.get_ldk_java_bindings_version())) throw new IllegalArgumentException("Compiled LDK library and LDK class failes do not match"); // Fetching the LDK versions from C also checks that the header and binaries match get_ldk_c_bindings_version(); @@ -71,9 +75,6 @@ public class bindings { static native void init_class_cache(); static native String get_lib_version_string(); - public static String get_ldk_java_bindings_version() { - return ""; - } public static native String get_ldk_c_bindings_version(); public static native String get_ldk_version(); @@ -90,6 +91,13 @@ public class bindings { public static native long new_empty_slice_vec(); """ + self.bindings_version_file = """package org.ldk.impl; + +public class version { + public static String get_ldk_java_bindings_version() { + return ""; + } +}""" self.bindings_footer = "}\n" @@ -107,7 +115,7 @@ import java.util.LinkedList; class CommonBase { long ptr; LinkedList ptrs_to = new LinkedList(); - protected CommonBase(long ptr) { assert ptr > 1024; this.ptr = ptr; } + protected CommonBase(long ptr) { assert ptr < 0 || ptr > 4096; this.ptr = ptr; } } """ @@ -153,7 +161,8 @@ void __attribute__((constructor)) spawn_stderr_redirection() { if not DEBUG or sys.platform == "darwin": self.c_file_pfx = self.c_file_pfx + """#define MALLOC(a, _) malloc(a) -#define FREE(p) if ((uint64_t)(p) > 1024) { free(p); } +#define FREE(p) if ((uint64_t)(p) > 4096) { free(p); } +#define CHECK_ACCESS(p) """ if not DEBUG: self.c_file_pfx += """#define DO_ASSERT(a) (void)(a) @@ -230,10 +239,11 @@ void backtrace_symbols_fd(void ** buffer, int count, int _fd) { self.c_file_pfx = self.c_file_pfx + "#include \n" self.c_file_pfx = self.c_file_pfx + """ #include -static mtx_t allocation_mtx; +#include +static pthread_mutex_t allocation_mtx; void __attribute__((constructor)) init_mtx() { - DO_ASSERT(mtx_init(&allocation_mtx, mtx_plain) == thrd_success); + DO_ASSERT(!pthread_mutex_init(&allocation_mtx, NULL)); } #define BT_MAX 128 @@ -255,10 +265,10 @@ static void new_allocation(void* res, const char* struct_name, size_t len) { new_alloc->struct_name = struct_name; new_alloc->bt_len = backtrace(new_alloc->bt, BT_MAX); new_alloc->alloc_len = len; - DO_ASSERT(mtx_lock(&allocation_mtx) == thrd_success); + DO_ASSERT(!pthread_mutex_lock(&allocation_mtx)); new_alloc->next = allocation_ll; allocation_ll = new_alloc; - DO_ASSERT(mtx_unlock(&allocation_mtx) == thrd_success); + DO_ASSERT(!pthread_mutex_unlock(&allocation_mtx)); } static void* MALLOC(size_t len, const char* struct_name) { void* res = __real_malloc(len); @@ -268,27 +278,27 @@ static void* MALLOC(size_t len, const char* struct_name) { void __real_free(void* ptr); static void alloc_freed(void* ptr) { allocation* p = NULL; - DO_ASSERT(mtx_lock(&allocation_mtx) == thrd_success); + DO_ASSERT(!pthread_mutex_lock(&allocation_mtx)); allocation* it = allocation_ll; while (it->ptr != ptr) { p = it; it = it->next; if (it == NULL) { - DEBUG_PRINT("Tried to free unknown pointer %p at:\\n", ptr); + DEBUG_PRINT("ERROR: Tried to free unknown pointer %p at:\\n", ptr); void* bt[BT_MAX]; int bt_len = backtrace(bt, BT_MAX); backtrace_symbols_fd(bt, bt_len, STDERR_FILENO); DEBUG_PRINT("\\n\\n"); - DO_ASSERT(mtx_unlock(&allocation_mtx) == thrd_success); + DO_ASSERT(!pthread_mutex_unlock(&allocation_mtx)); return; // addrsan should catch malloc-unknown and print more info than we have } } if (p) { p->next = it->next; } else { allocation_ll = it->next; } - DO_ASSERT(mtx_unlock(&allocation_mtx) == thrd_success); + DO_ASSERT(!pthread_mutex_unlock(&allocation_mtx)); DO_ASSERT(it->ptr == ptr); __real_free(it); } static void FREE(void* ptr) { - if ((uint64_t)ptr < 1024) return; // Rust loves to create pointers to the NULL page for dummys + if ((uint64_t)ptr <= 4096) return; // Rust loves to create pointers to the NULL page for dummys alloc_freed(ptr); __real_free(ptr); } @@ -309,6 +319,24 @@ void __wrap_free(void* ptr) { __real_free(ptr); } +static void CHECK_ACCESS(void* ptr) { + DO_ASSERT(!pthread_mutex_lock(&allocation_mtx)); + allocation* it = allocation_ll; + while (it->ptr != ptr) { + it = it->next; + if (it == NULL) { + DEBUG_PRINT("ERROR: Tried to access unknown pointer %p at:\\n", ptr); + void* bt[BT_MAX]; + int bt_len = backtrace(bt, BT_MAX); + backtrace_symbols_fd(bt, bt_len, STDERR_FILENO); + DEBUG_PRINT("\\n\\n"); + DO_ASSERT(!pthread_mutex_unlock(&allocation_mtx)); + return; // addrsan should catch and print more info than we have + } + } + DO_ASSERT(!pthread_mutex_unlock(&allocation_mtx)); +} + void* __real_realloc(void* ptr, size_t newlen); void* __wrap_realloc(void* ptr, size_t len) { if (ptr != NULL) alloc_freed(ptr); @@ -457,16 +485,17 @@ static inline LDKStr java_to_owned_str(JNIEnv *env, jstring str) { return res; } -JNIEXPORT jstring JNICALL Java_org_ldk_impl_bindings_get_1lib_1version_1string(JNIEnv *env, jclass _c) { - return str_ref_to_java(env, "", strlen("")); -} JNIEXPORT jstring JNICALL Java_org_ldk_impl_bindings_get_1ldk_1c_1bindings_1version(JNIEnv *env, jclass _c) { return str_ref_to_java(env, check_get_ldk_bindings_version(), strlen(check_get_ldk_bindings_version())); } JNIEXPORT jstring JNICALL Java_org_ldk_impl_bindings_get_1ldk_1version(JNIEnv *env, jclass _c) { return str_ref_to_java(env, check_get_ldk_version(), strlen(check_get_ldk_version())); } +#include "version.c" """ + self.c_version_file = """JNIEXPORT jstring JNICALL Java_org_ldk_impl_bindings_get_1lib_1version_1string(JNIEnv *env, jclass _c) { + return str_ref_to_java(env, "", strlen("")); +}""" self.hu_struct_file_prefix = """package org.ldk.structs; @@ -846,10 +875,13 @@ import javax.annotation.Nullable; out_c = out_c + "\t" + fn_line.ret_ty_info.c_ty + " ret = (*env)->CallObjectMethod(env, obj, j_calls->" + fn_line.fn_name + "_meth" elif fn_line.ret_ty_info.c_ty == "void": out_c += "\t(*env)->Call" + fn_line.ret_ty_info.java_ty.title() + "Method(env, obj, j_calls->" + fn_line.fn_name + "_meth" + elif fn_line.ret_ty_info.java_ty == "String": + # Manually write out String methods as they're just an Object + out_c += "\t" + fn_line.ret_ty_info.c_ty + " ret = (*env)->CallObjectMethod(env, obj, j_calls->" + fn_line.fn_name + "_meth" elif not fn_line.ret_ty_info.passed_as_ptr: out_c += "\t" + fn_line.ret_ty_info.c_ty + " ret = (*env)->Call" + fn_line.ret_ty_info.java_ty.title() + "Method(env, obj, j_calls->" + fn_line.fn_name + "_meth" else: - out_c = out_c + "\t" + fn_line.ret_ty_info.rust_obj + "* ret = (" + fn_line.ret_ty_info.rust_obj + "*)(*env)->CallLongMethod(env, obj, j_calls->" + fn_line.fn_name + "_meth" + out_c = out_c + "\tuint64_t ret = (*env)->CallLongMethod(env, obj, j_calls->" + fn_line.fn_name + "_meth" for idx, arg_info in enumerate(fn_line.args_ty): if arg_info.ret_conv is not None: @@ -1099,11 +1131,12 @@ import javax.annotation.Nullable; out_opaque_struct_human += self.hu_struct_file_prefix out_opaque_struct_human += "\n/**\n * " + struct_doc_comment.replace("\n", "\n * ") + "\n */\n" out_opaque_struct_human += "@SuppressWarnings(\"unchecked\") // We correctly assign various generic arrays\n" - out_opaque_struct_human += ("public class " + struct_name.replace("LDK","") + " extends CommonBase") + hu_name = struct_name.replace("LDKC2Tuple", "TwoTuple").replace("LDKC3Tuple", "ThreeTuple").replace("LDK", "") + out_opaque_struct_human += ("public class " + hu_name + " extends CommonBase") if struct_name.startswith("LDKLocked"): out_opaque_struct_human += (" implements AutoCloseable") out_opaque_struct_human += (" {\n") - out_opaque_struct_human += ("\t" + struct_name.replace("LDK", "") + "(Object _dummy, long ptr) { super(ptr); }\n") + out_opaque_struct_human += ("\t" + hu_name + "(Object _dummy, long ptr) { super(ptr); }\n") if struct_name.startswith("LDKLocked"): out_opaque_struct_human += ("\t@Override public void close() {\n") else: @@ -1114,8 +1147,10 @@ import javax.annotation.Nullable; out_opaque_struct_human += ("\t}\n\n") return out_opaque_struct_human + def map_tuple(self, struct_name): + return self.map_opaque_struct(struct_name, "A Tuple") - def map_function(self, argument_types, c_call_string, method_name, return_type_info, struct_meth, default_constructor_args, takes_self, takes_self_as_ref, args_known, type_mapping_generator, doc_comment): + def map_function(self, argument_types, c_call_string, method_name, meth_n, return_type_info, struct_meth, default_constructor_args, takes_self, takes_self_as_ref, args_known, type_mapping_generator, doc_comment): out_java = "" out_c = "" out_java_struct = None @@ -1142,7 +1177,6 @@ import javax.annotation.Nullable; if not args_known: out_java_struct += ("\t// Skipped " + method_name + "\n") else: - meth_n = method_name[len(struct_meth) + 1 if len(struct_meth) != 0 else 0:].strip("_") if doc_comment is not None: out_java_struct += "\t/**\n\t * " + doc_comment.replace("\n", "\n\t * ") + "\n\t */\n" if return_type_info.nullable: @@ -1173,7 +1207,10 @@ import javax.annotation.Nullable; else: if arg.nullable: out_java_struct += "@Nullable " - out_java_struct += (arg.java_hu_ty + " " + arg.arg_name) + ty_string = arg.java_hu_ty + if arg.java_fn_ty_arg[0] == "L" and arg.java_fn_ty_arg[len(arg.java_fn_ty_arg) - 1] == ";": + ty_string = arg.java_fn_ty_arg.strip("L;").replace("/", ".") + out_java_struct += ty_string + " " + arg.arg_name out_java += (");\n") out_c += (") {\n") if out_java_struct is not None: @@ -1240,7 +1277,7 @@ import javax.annotation.Nullable; out_java_struct += (info.arg_name) out_java_struct += (");\n") if return_type_info.java_ty == "long" and return_type_info.java_hu_ty != "long": - out_java_struct += "\t\tif (ret < 1024) { return null; }\n" + out_java_struct += "\t\tif (ret >= 0 && ret <= 4096) { return null; }\n" if return_type_info.to_hu_conv is not None: if not takes_self: