]> git.unchartedbackwaters.co.uk Git - francis/libjit.git/commitdiff
Clean up the breakpoint API and implement debug hooks for the interpreter.
authorRhys Weatherley <rweather@southern-storm.com.au>
Mon, 4 Oct 2004 02:26:41 +0000 (02:26 +0000)
committerRhys Weatherley <rweather@southern-storm.com.au>
Mon, 4 Oct 2004 02:26:41 +0000 (02:26 +0000)
19 files changed:
ChangeLog
doc/Makefile.am
doc/libjit.texi
include/jit/jit-context.h
include/jit/jit-insn.h
include/jit/jit-opcode.h
include/jit/jit-plus.h
jit/Makefile.am
jit/jit-context.c
jit/jit-debug.c [new file with mode: 0644]
jit/jit-function.c
jit/jit-insn.c
jit/jit-internal.h
jit/jit-interp.c
jit/jit-opcode.c
jit/jit-rules-arm.sel
jit/jit-rules-interp.c
jit/jit-rules-x86.sel
jitplus/jit-plus-function.cpp

index 53ce64971c732c1fcaa07667cb65da26e91a2d87..81ab682046f81b18d5448ea1eff14b8d43ee6d21 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -9,6 +9,15 @@
        add instructions and function API's for supporting debug line
        numbers and breakpoints.
 
+       * doc/Makefile.am, doc/libjit.texi, include/jit/jit-context.h,
+       include/jit/jit-insn.h, include/jit/jit-opcode.h,
+       include/jit/jit-plus.h, jit/Makefile.am, jit/jit-context.c,
+       jit/jit-debug.c, jit/jit-function.c, jit/jit-insn.c,
+       jit/jit-internal.h, jit/jit-interp.c, jit/jit-opcode.c,
+       jit/jit-rules-arm.sel, jit/jit-rules-interp.c, jit/jit-rules-x86.sel,
+       jitplus/jit-plus-function.cpp: clean up the breakpoint API and
+       implement debug hooks for the interpreter.
+
 2004-09-10  Rhys Weatherley  <rweather@southern-storm.com.au>
 
        * jit/jit-rules-x86.sel: pointer-relative loads and stores
index d20680c9730e21faf8c3f969d4603c117ddccfa6..2afa8e9a707e647e28dfffa23175d8ac4c3c3303 100644 (file)
@@ -8,6 +8,7 @@ libjit_TEXINFOS = \
        $(srcdir)/libjitext-apply.texi \
        $(srcdir)/libjitext-block.texi \
        $(srcdir)/libjitext-context.texi \
+       $(srcdir)/libjitext-debug.texi \
        $(srcdir)/libjitext-dump.texi \
        $(srcdir)/libjitext-dynlib.texi \
        $(srcdir)/libjitext-elf-read.texi \
@@ -41,6 +42,9 @@ $(srcdir)/libjitext-block.texi: $(top_srcdir)/jit/jit-block.c
 $(srcdir)/libjitext-context.texi: $(top_srcdir)/jit/jit-context.c
        $(SHELL) $(srcdir)/extract-docs.sh $< >$@
 
+$(srcdir)/libjitext-debug.texi: $(top_srcdir)/jit/jit-debug.c
+       $(SHELL) $(srcdir)/extract-docs.sh $< >$@
+
 $(srcdir)/libjitext-dump.texi: $(top_srcdir)/jit/jit-dump.c
        $(SHELL) $(srcdir)/extract-docs.sh $< >$@
 
index 067affe308e78e15efdb724899968cdf56d1136d..43c82b8dc40348c16bedb2230aaae496886a470b 100644 (file)
@@ -45,9 +45,10 @@ Copyright @copyright{} 2004 Southern Storm Software, Pty Ltd
 * Basic Blocks::            Working with basic blocks in the JIT
 * Intrinsics::              Intrinsic functions available to libjit users
 * Exceptions::              Handling exceptions
+* Breakpoint Debugging::    Hooking a breakpoint debugger into libjit
 * ELF Binaries::            Manipulating ELF binaries
 * Utility Routines::        Miscellaneous utility routines
-* Debugging Routines::      Debugging routines
+* Diagnostic Routines::     Diagnostic routines
 * C++ Interface::           Using libjit from C++
 * Porting::                 Porting libjit to new architectures
 * Why GPL?::                Why we use GPL and not LGPL for libjit
@@ -1014,7 +1015,7 @@ field with a @code{pointer to procedure/function} type.
 
 @c -----------------------------------------------------------------------
 
-@node Exceptions, ELF Binaries, Intrinsics, Top
+@node Exceptions, Breakpoint Debugging, Intrinsics, Top
 @chapter Handling exceptions
 @cindex Handling exceptions
 
@@ -1022,7 +1023,15 @@ field with a @code{pointer to procedure/function} type.
 
 @c -----------------------------------------------------------------------
 
-@node ELF Binaries, Utility Routines, Exceptions, Top
+@node Breakpoint Debugging, ELF Binaries, Exceptions, Top
+@chapter Hooking a breakpoint debugger into libjit
+@cindex Breakpoint debugging
+
+@include libjitext-debug.texi
+
+@c -----------------------------------------------------------------------
+
+@node ELF Binaries, Utility Routines, Breakpoint Debugging, Top
 @chapter Manipulating ELF binaries
 @cindex ELF binaries
 
@@ -1030,7 +1039,7 @@ field with a @code{pointer to procedure/function} type.
 
 @c -----------------------------------------------------------------------
 
-@node Utility Routines, Debugging Routines, ELF Binaries, Top
+@node Utility Routines, Diagnostic Routines, ELF Binaries, Top
 @chapter Miscellaneous utility routines
 @cindex Utility routines
 @cindex jit-util.h
@@ -1049,15 +1058,15 @@ that it itself uses internally, but which may also be useful to front ends.
 
 @c -----------------------------------------------------------------------
 
-@node Debugging Routines, C++ Interface, Utility Routines, Top
-@chapter Debugging routines
-@cindex Debugging routines
+@node Diagnostic Routines, C++ Interface, Utility Routines, Top
+@chapter Diagnostic routines
+@cindex Diagnostic routines
 
 @include libjitext-dump.texi
 
 @c -----------------------------------------------------------------------
 
-@node C++ Interface, C++ Contexts, Debugging Routines, Top
+@node C++ Interface, C++ Contexts, Diagnostic Routines, Top
 @chapter Using libjit from C++
 @cindex Using libjit from C++
 
index 33ff8ed125c8f98ab6ed8cb11a6bf42075b42e7a..87b46b9ae9ea481c3dfdd0711cea5e9d70f3c2d3 100644 (file)
@@ -41,6 +41,9 @@ void *jit_context_get_meta(jit_context_t context, int type) JIT_NOTHROW;
 jit_nuint jit_context_get_meta_numeric
        (jit_context_t context, int type) JIT_NOTHROW;
 void jit_context_free_meta(jit_context_t context, int type) JIT_NOTHROW;
+void jit_context_enable_all_breakpoints
+               (jit_context_t context, int flag) JIT_NOTHROW;
+int jit_context_all_breakpoints_enabled(jit_context_t context) JIT_NOTHROW;
 
 /*
  * Standard meta values for builtin configurable options.
@@ -49,6 +52,13 @@ void jit_context_free_meta(jit_context_t context, int type) JIT_NOTHROW;
 #define        JIT_OPTION_CACHE_PAGE_SIZE      10001
 #define        JIT_OPTION_PRE_COMPILE          10002
 #define        JIT_OPTION_DONT_FOLD            10003
+#define        JIT_OPTION_DEBUG_HOOK           10004
+
+/*
+ * Prototype for debug hook functions.
+ */
+typedef void (*jit_debug_hook_func)
+       (jit_function_t func, jit_nint data1, jit_nint data2);
 
 #ifdef __cplusplus
 };
index 299ee79f7c15236c04bb575acd9469436dd4b165..f39ce8f6fb1e640a418367425229b9e2e67a511f 100644 (file)
@@ -312,7 +312,7 @@ int jit_insn_move_blocks_to_start
 
 int jit_insn_mark_offset
        (jit_function_t func, jit_int offset) JIT_NOTHROW;
-int jit_insn_mark_debug
+int jit_insn_mark_breakpoint
        (jit_function_t func, jit_nint data1, jit_nint data2) JIT_NOTHROW;
 
 void jit_insn_iter_init(jit_insn_iter_t *iter, jit_block_t block) JIT_NOTHROW;
index ec370a54b909b2e78b732c6ff58d6a9e515e0ce5..8bc88d7b7dd699bac5d2525e5f38be7b256f4c3d 100644 (file)
@@ -515,7 +515,7 @@ extern      "C" {
  * Debugging support.
  */
 #define        JIT_OP_MARK_OFFSET                                      0x01A0
-#define        JIT_OP_MARK_DEBUG                                       0x01A1
+#define        JIT_OP_MARK_BREAKPOINT                          0x01A1
 
 /*
  * The number of opcodes in the above list.
index 6f118d57a302dcd2b9f10ce3ac8d2168e91af595..90535bf6b929c41ad5e054dc14501bb4ee28e47b 100644 (file)
@@ -351,7 +351,7 @@ public:
        void insn_move_blocks_to_start
                (const jit_label& from_label, const jit_label& to_label);
        void insn_mark_offset(jit_int offset);
-       void insn_mark_debug(jit_nint data1, jit_nint data2);
+       void insn_mark_breakpoint(jit_nint data1, jit_nint data2);
 
 private:
        jit_function_t func;
index 4bc7469fb11e1b7b83705a435042d761f37929c6..f87a2c8dbab40b070d7f0b23738c047b91be4814 100644 (file)
@@ -14,6 +14,7 @@ libjit_la_SOURCES = \
                jit-context.c \
                jit-cpuid-x86.h \
                jit-cpuid-x86.c \
+               jit-debug.c \
                jit-dump.c \
                jit-elf-defs.h \
                jit-elf-read.c \
index 4856d11e8bb0634580791ec13bbc2820ed2a0c01..b077df674f7f56baec95981fa884009efc5be1e8 100644 (file)
@@ -170,6 +170,21 @@ void jit_context_build_end(jit_context_t context)
  *
  * If the @code{type} already has some metadata associated with it, then
  * the previous value will be freed.
+ *
+ * The following non-numeric options are currently defined:
+ *
+ * @table @code
+ * @vindex JIT_OPTION_DEBUG_HOOK
+ * @item JIT_OPTION_DEBUG_HOOK
+ * Address of a function that should be called whenever an active
+ * breakpoint is encountered.  The prototype should be as follows:
+ *
+ * @example
+ * void hook(jit_function_t func, jit_nint data1, jit_nint data2);
+ * @end example
+ *
+ * @xref{Breakpoint Debugging}, for more information.
+ * @end table
  * @end deftypefun
 @*/
 int jit_context_set_meta
diff --git a/jit/jit-debug.c b/jit/jit-debug.c
new file mode 100644 (file)
index 0000000..e9d488e
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * jit-debug.c - Debug support routines for the JIT.
+ *
+ * Copyright (C) 2004  Southern Storm Software, Pty Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "jit-internal.h"
+
+/*@
+
+The @code{libjit} library provides a very simple breakpoint mechanism.
+Upon reaching each breakpoint in a function, the global debug hook
+is called.  It is up to the debug hook to decide whether to stop execution
+or to ignore the breakpoint.
+
+Typically, the debug hook will inspect a table to determine which
+breakpoints were actually selected by the user in a debugger's user
+interface.  The debug hook may even evaluate a complicated expression,
+taking the function, current thread, and the value of local variables
+into account, to make the decision.
+
+The global debug hook is set using @code{jit_context_set_meta} with a
+type argument of @code{JIT_OPTION_DEBUG_HOOK}.  It must have the
+following prototype:
+
+@example
+void hook(jit_function_t func, jit_nint data1, jit_nint data2);
+@end example
+
+The @code{func} argument indicates the function that the breakpoint
+occurred within.  The @code{data1} and @code{data2} arguments are
+those supplied to @code{jit_insn_mark_breakpoint}.  The debugger can use
+these values to indicate information about the breakpoint's type
+and location.
+
+If the hook decides to stop at the breakpoint, it can call the debugger
+immediately.  Or the hook can send a message to a separate debugger
+thread and wait for an indication that it is time to continue.
+
+Debug hooks can be used for other purposes besides breakpoint debugging.
+A program could be instrumented with hooks that tally up the number
+of times that each function is called, or which profile the amount of
+time spent in each function.
+
+@*/
+
+/*@
+ * @deftypefun int jit_insn_mark_breakpoint (jit_function_t func, jit_nint data1, jit_nint data2)
+ * Mark the current position in @code{func} as corresponding to a breakpoint
+ * location.  When a break occurs, the global debug hook is called with
+ * @code{func}, @code{data1}, and @code{data2} as arguments.
+ *
+ * Some platforms may have a performance penalty for inserting breakpoint
+ * locations, even if the breakpoint is never enabled.  Correctness is
+ * considered more important than performance where debugging is concerned.
+ * @end deftypefun
+@*/
+
+/*@
+ * @deftypefun void jit_context_enable_all_breakpoints (jit_context_t context, int flag)
+ * Enable or disable all breakpoints in all functions within @code{context}.
+ * This is typically used to implement a "single step" facility.
+ * @end deftypefun
+@*/
+void jit_context_enable_all_breakpoints(jit_context_t context, int flag)
+{
+       if(context)
+       {
+               context->breakpoints_enabled = flag;
+       }
+}
+
+/*@
+ * @deftypefun int jit_context_all_breakpoints_enabled (jit_context_t context)
+ * Determine if all breakpoints within @code{context} are enabled.
+ * @end deftypefun
+@*/
+int jit_context_all_breakpoints_enabled(jit_context_t context)
+{
+       if(context)
+       {
+               return context->breakpoints_enabled;
+       }
+       else
+       {
+               return 0;
+       }
+}
+
+/*@
+ * @deftypefun void jit_function_enable_breakpoints (jit_function_t func)
+ * Enable or disable all breakpoints in the specified function.
+ * @end deftypefun
+@*/
+void jit_function_enable_breakpoints(jit_function_t func, int flag)
+{
+       if(func)
+       {
+               func->breakpoints_enabled = flag;
+       }
+}
+
+/*@
+ * @deftypefun int jit_function_breakpoints_enabled (jit_function_t func)
+ * Determine if breakpoints are enabled on the specified function.
+ * @end deftypefun
+@*/
+int jit_function_breakpoints_enabled(jit_function_t func)
+{
+       if(func)
+       {
+               return func->breakpoints_enabled;
+       }
+       else
+       {
+               return 0;
+       }
+}
index 6e7f3d32985c41018624c71f42d96652c4015b55..dc1ab4c37ef0f57fa7b0418dd06c7863dafe0317 100644 (file)
@@ -1288,45 +1288,3 @@ unsigned int jit_function_get_max_optimization_level(void)
        /* TODO - implement more than basic optimization */
        return 0;
 }
-
-/*@
- * @deftypefun void jit_function_enable_breakpoints (jit_function_t func)
- * Enable or disable all breakpoints in the specified function.  Breakpoints
- * occur at locations marked by @code{jit_insn_mark_debug}.
- *
- * The @code{libjit} library provides a very simple breakpoint mechanism.
- * Upon reaching each breakpoint in the function, the global debug hook
- * is called.  It is up to the debug hook to decide whether to stop execution
- * or to ignore the breakpoint.
- *
- * Typically, the debug hook will inspect a table to determine which
- * breakpoints were actually selected by the user in a debugger's user
- * interface.  The debug hook may even evaluate a complicated expression,
- * taking the function, current thread, and the value of local variables
- * into account, to make the decision.
- * @end deftypefun
-@*/
-void jit_function_enable_breakpoints(jit_function_t func, int flag)
-{
-       if(func)
-       {
-               func->breakpoints_enabled = flag;
-       }
-}
-
-/*@
- * @deftypefun int jit_function_breakpoints_enabled (jit_function_t func)
- * Determine if breakpoints are enabled on the specified function.
- * @end deftypefun
-@*/
-int jit_function_breakpoints_enabled(jit_function_t func)
-{
-       if(func)
-       {
-               return func->breakpoints_enabled;
-       }
-       else
-       {
-               return 0;
-       }
-}
index e334eef38bf8096f8049b9d7f63b31fae899afbe..75924b365e3fa55682c8158315b28c9a64b284aa 100644 (file)
@@ -7694,23 +7694,15 @@ int jit_insn_mark_offset(jit_function_t func, jit_int offset)
                                                                (func, jit_type_int, offset));
 }
 
-/*@
- * @deftypefun int jit_insn_mark_debug (jit_function_t func, jit_nint data1, jit_nint data2)
- * Mark the current position in @code{func} as corresponding to a breakpoint
- * location.  When a break occurs, the global debug hook is called with
- * @code{func}, @code{data1}, and @code{data2} as arguments.  See the
- * description for @code{jit_function_enable_breakpoints} for more
- * information on breakpoint support.
- * @end deftypefun
-@*/
-int jit_insn_mark_debug
+/* Documentation is in jit-debug.c */
+int jit_insn_mark_breakpoint
        (jit_function_t func, jit_nint data1, jit_nint data2)
 {
        if(!jit_insn_new_block(func))
        {
                return 0;
        }
-       return create_note(func, JIT_OP_MARK_DEBUG,
+       return create_note(func, JIT_OP_MARK_BREAKPOINT,
                                       jit_value_create_nint_constant
                                                        (func, jit_type_nint, data1),
                                       jit_value_create_nint_constant
index 4afbe51df345e85e2cd07aae08e7b8bc71c3089a..e1ec2246b402b810a5c4da97366c78872d5c050e 100644 (file)
@@ -458,6 +458,9 @@ struct _jit_context
        /* Table of symbols that have been registered with this context */
        jit_regsym_t       *registered_symbols;
        int                                     num_registered_symbols;
+
+       /* Flag that is set if all breakpoints in the system are enabled */
+       int volatile            breakpoints_enabled;
 };
 
 /*
index 0de6402fe23a790585af934b52f32e6a40eb3766..8cf2b082b808578b895ded45c45ea816f5441323 100644 (file)
@@ -4460,10 +4460,21 @@ void _jit_run_function(jit_function_interp_t func, jit_item *args,
                 * Debugging support.
                 ******************************************************************/
 
-               VMCASE(JIT_OP_MARK_DEBUG):
+               VMCASE(JIT_OP_MARK_BREAKPOINT):
                {
                        /* Process a breakpoint within the current function */
-                       /* TODO */
+                       if(func->func->breakpoints_enabled ||
+                          func->func->context->breakpoints_enabled)
+                       {
+                               jit_debug_hook_func hook;
+                               hook = (jit_debug_hook_func)
+                                       jit_context_get_meta(func->func->context,
+                                                                                JIT_OPTION_DEBUG_HOOK);
+                               if(hook)
+                               {
+                                       (*hook)(func->func, VM_NINT_ARG, VM_NINT_ARG2);
+                               }
+                       }
                        VM_MODIFY_PC_AND_STACK(3, 0);
                }
                VMBREAK;
index 0d2a9924808cd3d1ac5abcdc54bcf76fb66191bd..b6c9806a865a43930b55920f9f0929cfaa7ad508 100644 (file)
@@ -530,8 +530,8 @@ jit_opcode_info_t const jit_opcodes[JIT_OP_NUM_OPCODES] = {
        /*
         * Debugging support.
         */
-       {"mark_offset",                                         F_(EMPTY, INT, EMPTY)},
-       {"mark_debug",                                          F_(EMPTY, PTR, PTR)},
+       {"mark_offset",                                 F_(EMPTY, INT, EMPTY)},
+       {"mark_breakpoint",                             F_(EMPTY, PTR, PTR)},
 
 };
 
index d41b761770bb6afb93cd9f4ff5535089cd638ba4..e27304e26d24773a312ccfa96fb7904f2d7f5273 100644 (file)
@@ -1404,7 +1404,7 @@ JIT_OP_ADD_RELATIVE: unary
  * Debugging support.
  */
 
-JIT_OP_MARK_DEBUG: manual
+JIT_OP_MARK_BREAKPOINT: manual
        [] -> {
                /* TODO */
                TODO();
index e8ceefca8c241f0f782e29c1312a55f37e5c5bb0..27b7914ac29a5a5cd10372a1ae208ebdd38d5651 100644 (file)
@@ -1631,7 +1631,7 @@ void _jit_gen_insn(jit_gencode_t gen, jit_function_t func,
                }
                break;
 
-               case JIT_OP_MARK_DEBUG:
+               case JIT_OP_MARK_BREAKPOINT:
                {
                        /* Mark the current location as a potential breakpoint */
                        jit_cache_opcode(&(gen->posn), insn->opcode);
index 2d7f612586ddd8b25a6be1309cbe9721596399ea..c29d739cd9ce077f1412e75f9a133d788fc876b1 100644 (file)
@@ -2805,7 +2805,7 @@ JIT_OP_ALLOCA: unary
  * Debugging support.
  */
 
-JIT_OP_MARK_DEBUG: manual
+JIT_OP_MARK_BREAKPOINT: manual
        [] -> {
                /* TODO */
                TODO();
index df486a7be022ccd57ddb01317f7787b331fde928..4fcf3bf6897fd5821e3e53ee79391f96392638ea 100644 (file)
@@ -673,7 +673,7 @@ jit_value jit_function::get_struct_pointer()
  * @deftypemethodx jit_function void insn_move_blocks_to_end ({const jit_label&} from_label, {const jit_label&} to_label)
  * @deftypemethodx jit_function void insn_move_blocks_to_start ({const jit_label&} from_label, {const jit_label&} to_label)
  * @deftypemethodx jit_function void insn_mark_offset (jit_int offset)
- * @deftypemethodx jit_function void insn_mark_debug (jit_nint data1, jit_nint data2)
+ * @deftypemethodx jit_function void insn_mark_breakpoint (jit_nint data1, jit_nint data2)
  * Create instructions of various kinds.  @xref{Instructions}, for more
  * information on the individual instructions and their arguments.
  * @end deftypemethod
@@ -1436,9 +1436,9 @@ void jit_function::insn_mark_offset(jit_int offset)
        }
 }
 
-void jit_function::insn_mark_debug(jit_nint data1, jit_nint data2)
+void jit_function::insn_mark_breakpoint(jit_nint data1, jit_nint data2)
 {
-       if(!jit_insn_mark_debug(func, data1, data2))
+       if(!jit_insn_mark_breakpoint(func, data1, data2))
        {
                out_of_memory();
        }