]> git.unchartedbackwaters.co.uk Git - francis/libjit.git/commitdiff
add unwinding interface
authorAleksey Demakov <ademakov@gmail.com>
Thu, 29 May 2008 21:03:30 +0000 (21:03 +0000)
committerAleksey Demakov <ademakov@gmail.com>
Thu, 29 May 2008 21:03:30 +0000 (21:03 +0000)
ChangeLog
include/jit/Makefile.am
include/jit/jit-unwind.h [new file with mode: 0644]
include/jit/jit.h
jit/Makefile.am
jit/jit-except.c
jit/jit-unwind.c [new file with mode: 0644]

index 210bb46286f3dd67a304931db00a735adb2eb37a..66a9f56d3efb98990e16c1b7396c3563acd5817e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -4,7 +4,14 @@
        type.
 
        * include/jit/jit-except.h, include/jit/jit-common.h: move
-       JIT_NO_OFFSET from jit-except.h to jit-common.h
+       JIT_NO_OFFSET from jit-except.h to jit-common.h.
+
+       * include/jit/jit-unwind.h, jit/jit-unwind.c: new files.
+       * include/jit/jit.h, include/jit/Makefile.am: add jit-unwind.h.
+       * jit/Makefile.am: add jit-unwind.c.
+
+       * jit/jit-except.c (jit_exception_get_stack_trace): re-implement
+       using unwind routines.
 
 2008-05-28  Juan Jesus Garcia de Soria  <juanj.g_soria@grupobbva.com>
 
index c676d89d1043df4568881b9d63505b4d8c1b5a9d..4ec9bf1134f4c5b36c55e9432f72d961cdf0a0b1 100644 (file)
@@ -3,31 +3,33 @@ ARCH_HEADER = jit-arch-@JIT_ARCH@.h
 BUILT_SOURCES = jit-arch.h
 
 libjitincludedir = $(includedir)/jit
-libjitinclude_HEADERS = jit.h \
-                                               jit-arch.h \
-                                               jit-apply.h \
-                                               jit-block.h \
-                                               jit-common.h \
-                                               jit-context.h \
-                                               jit-debugger.h \
-                                               jit-defs.h \
-                                               jit-dump.h \
-                                               jit-dynamic.h \
-                                               jit-elf.h \
-                                               jit-except.h \
-                                               jit-function.h \
-                                               jit-init.h \
-                                               jit-insn.h \
-                                               jit-intrinsic.h \
-                                               jit-meta.h \
-                                               jit-objmodel.h \
-                                               jit-objmodel-private.h \
-                                               jit-opcode.h \
-                                               jit-plus.h \
-                                               jit-type.h \
-                                               jit-util.h \
-                                               jit-value.h \
-                                               jit-walk.h
+libjitinclude_HEADERS = \
+       jit.h \
+       jit-arch.h \
+       jit-apply.h \
+       jit-block.h \
+       jit-common.h \
+       jit-context.h \
+       jit-debugger.h \
+       jit-defs.h \
+       jit-dump.h \
+       jit-dynamic.h \
+       jit-elf.h \
+       jit-except.h \
+       jit-function.h \
+       jit-init.h \
+       jit-insn.h \
+       jit-intrinsic.h \
+       jit-meta.h \
+       jit-objmodel.h \
+       jit-objmodel-private.h \
+       jit-opcode.h \
+       jit-plus.h \
+       jit-type.h \
+       jit-unwind.h \
+       jit-util.h \
+       jit-value.h \
+       jit-walk.h
 
 noinst_HEADERS = jit-arch-generic.h jit-arch-x86.h jit-arch-x86-64.h
 
diff --git a/include/jit/jit-unwind.h b/include/jit/jit-unwind.h
new file mode 100644 (file)
index 0000000..822d65d
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * jit-unwind.h - Routines for performing stack unwinding.
+ *
+ * Copyright (C) 2008  Southern Storm Software, Pty Ltd.
+ *
+ * This file is part of the libjit library.
+ *
+ * The libjit library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation, either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * The libjit library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the libjit library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef        _JIT_UNWIND_H
+#define        _JIT_UNWIND_H
+
+#include <jit/jit-common.h>
+#include <jit/jit-arch.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct
+{
+       void *frame;
+       void *cache;
+       jit_context_t context;
+#ifdef _JIT_ARCH_UNWIND_DATA
+       _JIT_ARCH_UNWIND_DATA
+#endif
+} jit_unwind_context_t;
+
+int jit_unwind_init(jit_unwind_context_t *unwind, jit_context_t context);
+void jit_unwind_free(jit_unwind_context_t *unwind);
+
+int jit_unwind_next(jit_unwind_context_t *unwind);
+int jit_unwind_next_pc(jit_unwind_context_t *unwind);
+void *jit_unwind_get_pc(jit_unwind_context_t *unwind);
+
+int jit_unwind_jump(jit_unwind_context_t *unwind, void *pc);
+
+jit_function_t jit_unwind_get_function(jit_unwind_context_t *unwind);
+unsigned int jit_unwind_get_offset(jit_unwind_context_t *unwind);
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif /* _JIT_UNWIND_H */
index 46ea6cb82462be164f0b06ad2cb74d4b6ae10fca..0cbdc754d10a96ff470437610de53c377fafdfae 100644 (file)
@@ -36,11 +36,12 @@ extern      "C" {
 #include <jit/jit-function.h>
 #include <jit/jit-init.h>
 #include <jit/jit-insn.h>
+#include <jit/jit-intrinsic.h>
 #include <jit/jit-meta.h>
 #include <jit/jit-objmodel.h>
 #include <jit/jit-opcode.h>
 #include <jit/jit-type.h>
-#include <jit/jit-intrinsic.h>
+#include <jit/jit-unwind.h>
 #include <jit/jit-util.h>
 #include <jit/jit-value.h>
 #include <jit/jit-walk.h>
index 254b27650f49a671531caa2a824f9db038e8738c..68588e48a14570e57f53236e65237fc6e53e8297 100644 (file)
@@ -2,84 +2,85 @@
 lib_LTLIBRARIES = libjit.la
 
 libjit_la_SOURCES = \
-               jit-alloc.c \
-               jit-apply.c \
-               jit-apply-func.h \
-               jit-apply-alpha.h \
-               jit-apply-alpha.c \
-               jit-apply-arm.h \
-               jit-apply-arm.c \
-               jit-apply-x86.h \
-               jit-apply-x86.c \
-               jit-apply-x86-64.h \
-               jit-apply-x86-64.c \
-               jit-bitset.h \
-               jit-bitset.c \
-               jit-block.c \
-               jit-cache.h \
-               jit-cache.c \
-               jit-cfg.h \
-               jit-cfg.c \
-               jit-context.c \
-               jit-cpuid-x86.h \
-               jit-cpuid-x86.c \
-               jit-debugger.c \
-               jit-dump.c \
-               jit-elf-defs.h \
-               jit-elf-read.c \
-               jit-elf-write.c \
-               jit-except.c \
-               jit-function.c \
-               jit-gen-alpha.h \
-               jit-gen-arm.h \
-               jit-gen-arm.c \
-               jit-gen-x86.h \
-               jit-gen-x86-64.h \
-               jit-insn.c \
-               jit-init.c \
-               jit-internal.h \
-               jit-interp.h \
-               jit-interp.c \
-               jit-intrinsic.c \
-               jit-live.c \
-               jit-memory.c \
-               jit-memory.h \
-               jit-meta.c \
-               jit-objmodel.c \
-               jit-opcode.c \
-               jit-pool.c \
-               jit-reg-alloc.h \
-               jit-reg-alloc.c \
-               jit-reg-class.h \
-               jit-reg-class.c \
-               jit-rules.h \
-               jit-rules.c \
-               jit-rules-interp.c \
-               jit-rules-interp.h \
-               jit-rules-alpha.h \
-               jit-rules-alpha.c \
-               jit-rules-arm.h \
-               jit-rules-arm.c \
-               jit-rules-x86.h \
-               jit-rules-x86.c \
-               jit-rules-x86-64.h \
-               jit-rules-x86-64.c \
-               jit-setjmp.h \
-               jit-signal.c \
-               jit-string.c \
-               jit-symbol.c \
-               jit-thread.c \
-               jit-thread.h \
-               jit-type.c \
-               jit-value.c \
-               jit-walk.c
+       jit-alloc.c \
+       jit-apply.c \
+       jit-apply-func.h \
+       jit-apply-alpha.h \
+       jit-apply-alpha.c \
+       jit-apply-arm.h \
+       jit-apply-arm.c \
+       jit-apply-x86.h \
+       jit-apply-x86.c \
+       jit-apply-x86-64.h \
+       jit-apply-x86-64.c \
+       jit-bitset.h \
+       jit-bitset.c \
+       jit-block.c \
+       jit-cache.h \
+       jit-cache.c \
+       jit-cfg.h \
+       jit-cfg.c \
+       jit-context.c \
+       jit-cpuid-x86.h \
+       jit-cpuid-x86.c \
+       jit-debugger.c \
+       jit-dump.c \
+       jit-elf-defs.h \
+       jit-elf-read.c \
+       jit-elf-write.c \
+       jit-except.c \
+       jit-function.c \
+       jit-gen-alpha.h \
+       jit-gen-arm.h \
+       jit-gen-arm.c \
+       jit-gen-x86.h \
+       jit-gen-x86-64.h \
+       jit-insn.c \
+       jit-init.c \
+       jit-internal.h \
+       jit-interp.h \
+       jit-interp.c \
+       jit-intrinsic.c \
+       jit-live.c \
+       jit-memory.c \
+       jit-memory.h \
+       jit-meta.c \
+       jit-objmodel.c \
+       jit-opcode.c \
+       jit-pool.c \
+       jit-reg-alloc.h \
+       jit-reg-alloc.c \
+       jit-reg-class.h \
+       jit-reg-class.c \
+       jit-rules.h \
+       jit-rules.c \
+       jit-rules-interp.c \
+       jit-rules-interp.h \
+       jit-rules-alpha.h \
+       jit-rules-alpha.c \
+       jit-rules-arm.h \
+       jit-rules-arm.c \
+       jit-rules-x86.h \
+       jit-rules-x86.c \
+       jit-rules-x86-64.h \
+       jit-rules-x86-64.c \
+       jit-setjmp.h \
+       jit-signal.c \
+       jit-string.c \
+       jit-symbol.c \
+       jit-thread.c \
+       jit-thread.h \
+       jit-type.c \
+       jit-unwind.c \
+       jit-value.c \
+       jit-walk.c
 
 EXTRA_DIST = \
-               mklabel.sh \
-               jit-rules-alpha.ins \
-               jit-rules-arm.sel \
-               jit-rules-x86.ins \
-               jit-rules-x86-64.ins
+       mklabel.sh \
+       jit-rules-alpha.ins \
+       jit-rules-arm.sel \
+       jit-rules-x86.ins \
+       jit-rules-x86-64.ins
 
 AM_CFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include -I. -I$(srcdir)
 
index bd6d613e5ea0bde461ab7ed21505e74dcfe50d3a..a4ad75e6cb17473b0fccb475f99a8547486e6897 100644 (file)
@@ -305,32 +305,32 @@ struct jit_stack_trace
 @*/
 jit_stack_trace_t jit_exception_get_stack_trace(void)
 {
-       jit_stack_trace_t trace = 0;
-       unsigned int size = 0;
-#if JIT_APPLY_BROKEN_FRAME_BUILTINS != 0
-       jit_thread_control_t control;
-       jit_backtrace_t top;
-       jit_backtrace_t item;
-       
+       jit_stack_trace_t trace;
+       unsigned int size;
+       jit_unwind_context_t unwind;
+
        /* Count the number of items in the current thread's call stack */
-       control = _jit_thread_get_control();
-       if(!control)
+       size = 0;
+       if(jit_unwind_init(&unwind, NULL))
        {
-               return 0;
+               do
+               {
+                       size++;
+               }
+               while(jit_unwind_next_pc(&unwind));
+               jit_unwind_free(&unwind);
        }
-       size = 0;
-       top = control->backtrace_head;
-       item = top;
-       while(item != 0)
+
+       /* Bail out if the stack is not available */
+       if(size == 0)
        {
-               ++size;
-               item = item->parent;
+               return 0;
        }
 
        /* Allocate memory for the stack trace */
-       trace = (jit_stack_trace_t)jit_malloc
-               (sizeof(struct jit_stack_trace) +
-                size * sizeof(void *) - sizeof(void *));
+       trace = (jit_stack_trace_t) jit_malloc(sizeof(struct jit_stack_trace)
+                                              + size * sizeof(void *)
+                                              - sizeof(void *));
        if(!trace)
        {
                return 0;
@@ -339,43 +339,22 @@ jit_stack_trace_t jit_exception_get_stack_trace(void)
 
        /* Populate the stack trace with the items we counted earlier */
        size = 0;
-       item = top;
-       while(item != 0)
-       {
-               trace->items[size] = item->pc;
-               ++size;
-               item = item->parent;
-       }
-#else
-       void *frame = jit_get_current_frame();
-
-       /* Count the number of items in the current thread's call stack */
-       while(frame != 0)
+       if(jit_unwind_init(&unwind, NULL))
        {
-               frame = jit_get_next_frame_address(frame);
-               ++size;
+               do
+               {
+                       trace->items[size] = jit_unwind_get_pc(&unwind);
+                       size++;
+               }
+               while(jit_unwind_next_pc(&unwind));
+               jit_unwind_free(&unwind);
        }
-
-       /* Allocate memory for the stack trace */
-       trace = (jit_stack_trace_t)jit_malloc
-               (sizeof(struct jit_stack_trace) +
-                size * sizeof(void *) - sizeof(void *));
-       if(!trace)
+       else
        {
+               jit_free(trace);
                return 0;
        }
-       trace->size = size;
 
-       /* Populate the stack trace with the items we counted earlier */
-       size = 0;
-       frame = jit_get_current_frame();
-       while(frame != 0)
-       {
-               trace->items[size] = jit_get_return_address(frame);
-               frame = jit_get_next_frame_address(frame);
-               ++size;
-       }
-#endif
        return trace;
 }
 
@@ -469,7 +448,7 @@ unsigned int jit_stack_trace_get_offset
                        }
                }
        }
-       return JIT_CACHE_NO_OFFSET;
+       return JIT_NO_OFFSET;
 }
 
 /*@
diff --git a/jit/jit-unwind.c b/jit/jit-unwind.c
new file mode 100644 (file)
index 0000000..d88d6de
--- /dev/null
@@ -0,0 +1,212 @@
+/*
+ * jit-unwind.c - Routines for performing stack unwinding.
+ *
+ * Copyright (C) 2008  Southern Storm Software, Pty Ltd.
+ *
+ * This file is part of the libjit library.
+ *
+ * The libjit library is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation, either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * The libjit library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the libjit library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include "jit-internal.h"
+#include "jit-cache.h"
+#include "jit-rules.h"
+#include "jit-apply-rules.h"
+#include <jit/jit-unwind.h>
+#include <jit/jit-walk.h>
+
+int
+jit_unwind_init(jit_unwind_context_t *unwind, jit_context_t context)
+{
+#if defined(JIT_BACKENED_INTERP) || JIT_APPLY_BROKEN_FRAME_BUILTINS != 0
+       jit_thread_control_t control;
+
+       control = _jit_thread_get_control();
+       if(!control)
+       {
+               return 0;
+       }
+
+       unwind->frame = control->backtrace_head;
+#elif JIT_FAST_GET_CURRENT_FRAME != 0
+       unwind->frame = jit_get_next_frame_address(jit_get_current_frame());
+#else
+       unwind->frame = jit_get_frame_address(1);
+#endif
+
+       unwind->context = context;
+       unwind->cache = 0;
+
+#ifdef _JIT_ARCH_UNWIND_INIT
+       _JIT_ARCH_UNWIND_INIT(unwind);
+#endif
+
+       return (unwind->frame != 0);
+}
+
+void
+jit_unwind_free(jit_unwind_context_t *unwind)
+{
+#ifdef _JIT_ARCH_UNWIND_FREE
+       _JIT_ARCH_UNWIND_FREE(unwind);
+#endif
+}
+
+int
+jit_unwind_next(jit_unwind_context_t *unwind)
+{
+#if defined(_JIT_ARCH_UNWIND_NEXT) || defined(_JIT_ARCH_UNWIND_NEXT_PRE)
+       jit_function_t func;
+#endif
+
+       if(!unwind || !unwind->frame)
+       {
+               return 0;
+       }
+
+       unwind->cache = 0;
+
+#if defined(JIT_BACKENED_INTERP) || JIT_APPLY_BROKEN_FRAME_BUILTINS != 0
+       unwind->frame =  ((jit_backtrace_t) unwind->frame)->parent;
+       return (unwind->frame != 0);
+#else
+
+#ifdef _JIT_ARCH_UNWIND_NEXT_PRE
+       func = jit_unwind_get_function(unwind);
+       if(func)
+       {
+               _JIT_ARCH_UNWIND_NEXT_PRE(unwind, func);
+       }
+#endif
+
+       unwind->frame = jit_get_next_frame_address(unwind->frame);
+       if(!unwind->frame)
+       {
+               return 0;
+       }
+
+#ifdef _JIT_ARCH_UNWIND_NEXT
+       func = jit_unwind_get_function(unwind);
+       if(func)
+       {
+               _JIT_ARCH_UNWIND_NEXT(unwind, func);
+       }
+#endif
+
+       return 1;
+#endif
+}
+
+int
+jit_unwind_next_pc(jit_unwind_context_t *unwind)
+{
+       if(!unwind || !unwind->frame)
+       {
+               return 0;
+       }
+
+       unwind->cache = 0;
+
+#if defined(JIT_BACKENED_INTERP) || JIT_APPLY_BROKEN_FRAME_BUILTINS != 0
+       unwind->frame =  ((jit_backtrace_t) unwind->frame)->parent;
+#else
+       unwind->frame = jit_get_next_frame_address(unwind->frame);
+#endif
+       return (unwind->frame != 0);
+}
+
+void *
+jit_unwind_get_pc(jit_unwind_context_t *unwind)
+{
+       if(!unwind || !unwind->frame)
+       {
+               return 0;
+       }
+
+#if defined(JIT_BACKENED_INTERP) || JIT_APPLY_BROKEN_FRAME_BUILTINS != 0
+       return ((jit_backtrace_t) unwind->frame)->pc;
+#else
+       return jit_get_return_address(unwind->frame);
+#endif
+}
+
+int
+jit_unwind_jump(jit_unwind_context_t *unwind, void *pc)
+{
+#ifdef _JIT_ARCH_UNWIND_JUMP
+       if(!unwind || !unwind->frame || !pc)
+       {
+               return 0;
+       }
+
+       return _JIT_ARCH_UNWIND_JUMP(unwind, pc);
+#else
+       return 0;
+#endif
+}
+
+jit_function_t
+jit_unwind_get_function(jit_unwind_context_t *unwind)
+{
+       if(!unwind || !unwind->frame || !unwind->context)
+       {
+               return 0;
+       }
+
+       if(!unwind->cache)
+       {
+               jit_cache_t cache = _jit_context_get_cache(unwind->context);
+               void *pc = jit_unwind_get_pc(unwind);
+               unwind->cache = (jit_function_t)
+                       _jit_cache_get_method(cache, pc, NULL);
+       }
+
+       return (jit_function_t) unwind->cache;
+}
+
+unsigned int
+jit_unwind_get_offset(jit_unwind_context_t *unwind)
+{
+       jit_function_t func;
+       jit_cache_t cache;
+       void *pc, *start;
+
+       if(!unwind || !unwind->frame || !unwind->context)
+       {
+               return JIT_NO_OFFSET;
+       }
+
+       pc = jit_unwind_get_pc(unwind);
+       if(!pc)
+       {
+               return JIT_NO_OFFSET;
+       }
+
+       func = jit_unwind_get_function(unwind);
+       if(!func)
+       {
+               return JIT_NO_OFFSET;
+       }
+
+       cache = _jit_context_get_cache(unwind->context);
+
+#ifdef JIT_PROLOG_SIZE
+       start = _jit_cache_get_start_method(cache, func->entry_point);
+#else
+       start = func->entry_point;
+#endif
+
+       return _jit_cache_get_bytecode(cache, start, pc - start, 0);
+}