When JNI method linking fails an instance of java.lang.UnsatisfiedLinkError is thrown from JNI trampoline (jit_native_trampoline()). When stack trace is created for this exception, stack walker is trying to use the method->compilation_unit->native_ptr to get the JNI method's address, but this pointer is not valid because linking failed. To solve this problem we add a new field to struct stack_trace_elem to hold a pointer to compilation unit. For JNI stack trace elements this field is used and no jit_lookup_cu() is performed on ->addr. This also makes stack traversal faster.
Signed-off-by: Tomek Grabiec <tgrab...@gmail.com> --- include/vm/stack-trace.h | 3 +++ jit/trampoline.c | 6 ++++++ vm/stack-trace.c | 21 +++++++++++---------- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/include/vm/stack-trace.h b/include/vm/stack-trace.h index 4bde292..f6db886 100644 --- a/include/vm/stack-trace.h +++ b/include/vm/stack-trace.h @@ -124,6 +124,8 @@ struct stack_trace_elem { * is undefined. */ void *frame; + + struct compilation_unit *cu; }; void init_stack_trace_printing(void); @@ -131,6 +133,7 @@ int init_stack_trace_elem(struct stack_trace_elem *elem); int get_prev_stack_trace_elem(struct stack_trace_elem *elem); int skip_frames_from_class(struct stack_trace_elem *elem, struct vm_class *class); int get_stack_trace_depth(struct stack_trace_elem *elem); +struct compilation_unit *stack_trace_elem_get_cu(struct stack_trace_elem *elem); struct vm_object *get_stack_trace(void); struct vm_object *get_stack_trace_from_ctx(void *ctx); struct vm_object *native_vmthrowable_fill_in_stack_trace(struct vm_object *); diff --git a/jit/trampoline.c b/jit/trampoline.c index 415d4d5..369da6d 100644 --- a/jit/trampoline.c +++ b/jit/trampoline.c @@ -81,6 +81,12 @@ static void *jit_native_trampoline(struct compilation_unit *cu) signal_new_exception(vm_java_lang_UnsatisfiedLinkError, msg->value); free_str(msg); + /* We must remove the jni_stack_entry from call stack here + * because we're not returning after call site - exception + * will be caught by trampoline code. + */ + vm_leave_jni(); + return NULL; } diff --git a/vm/stack-trace.c b/vm/stack-trace.c index 45ad794..76f4a50 100644 --- a/vm/stack-trace.c +++ b/vm/stack-trace.c @@ -221,14 +221,7 @@ static int get_caller_stack_trace_elem(struct stack_trace_elem *elem) elem->type = STACK_TRACE_ELEM_TYPE_JNI; elem->is_native = false; - /* - * We don't need to lock the compilation_unit - * because when JNI method is present in stack - * trace it means that it has been resolved - * and ->native_ptr can not change after that. - */ - elem->addr = (unsigned long) - tr->method->compilation_unit->native_ptr; + elem->cu = tr->method->compilation_unit; elem->frame = NULL; return 0; } @@ -335,6 +328,14 @@ int init_stack_trace_elem(struct stack_trace_elem *elem) return get_prev_stack_trace_elem(elem); } +struct compilation_unit *stack_trace_elem_get_cu(struct stack_trace_elem *elem) +{ + if (elem->type == STACK_TRACE_ELEM_TYPE_JNI) + return elem->cu; + + return jit_lookup_cu(elem->addr); +} + /** * skip_frames_from_class - makes @elem to point to the nearest stack * trace element which does not belong to any method of class @@ -349,7 +350,7 @@ int skip_frames_from_class(struct stack_trace_elem *elem, struct compilation_unit *cu; do { - cu = jit_lookup_cu(elem->addr); + cu = stack_trace_elem_get_cu(elem); if (cu == NULL) { fprintf(stderr, "%s: no compilation unit mapping for %p\n", @@ -420,7 +421,7 @@ static struct vm_object *get_intermediate_stack_trace(void) do { unsigned long bc_offset; - cu = jit_lookup_cu(st_elem.addr); + cu = stack_trace_elem_get_cu(&st_elem); if (!cu) { fprintf(stderr, "%s: no compilation unit mapping for %p\n", -- 1.6.0.6 ------------------------------------------------------------------------------ _______________________________________________ Jatovm-devel mailing list Jatovm-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/jatovm-devel