github.com/goccy/go-jit@v0.0.0-20200514131505-ff78d45cf6af/internal/ccall/jit-debugger.c (about)

     1  /*
     2   * jit-debugger.c - Helper routines for single-step debugging of programs.
     3   *
     4   * Copyright (C) 2004  Southern Storm Software, Pty Ltd.
     5   *
     6   * This file is part of the libjit library.
     7   *
     8   * The libjit library is free software: you can redistribute it and/or
     9   * modify it under the terms of the GNU Lesser General Public License
    10   * as published by the Free Software Foundation, either version 2.1 of
    11   * the License, or (at your option) any later version.
    12   *
    13   * The libjit library is distributed in the hope that it will be useful,
    14   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    15   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    16   * Lesser General Public License for more details.
    17   *
    18   * You should have received a copy of the GNU Lesser General Public
    19   * License along with the libjit library.  If not, see
    20   * <http://www.gnu.org/licenses/>.
    21   */
    22  
    23  #include "jit-internal.h"
    24  
    25  /*@
    26  
    27  @cindex jit-debugger.h
    28  
    29  The @code{libjit} library provides support routines for breakpoint-based
    30  single-step debugging.  It isn't a full debugger, but provides the
    31  infrastructure necessary to support one.
    32  
    33  The front end virtual machine is responsible for inserting "potential
    34  breakpoints" into the code when functions are built and compiled.  This
    35  is performed using @code{jit_insn_mark_breakpoint}:
    36  
    37  @deftypefun int jit_insn_mark_breakpoint (jit_function_t @var{func}, jit_nint @var{data1}, jit_nint @var{data2})
    38  Mark the current position in @var{func} as corresponding to a breakpoint
    39  location.  When a break occurs, the debugging routines are passed
    40  @var{func}, @var{data1}, and @var{data2} as arguments.  By convention,
    41  @var{data1} is the type of breakpoint (source line, function entry,
    42  function exit, etc).
    43  @end deftypefun
    44  
    45  There are two ways for a front end to receive notification about breakpoints.
    46  The bulk of this chapter describes the @code{jit_debugger_t} interface,
    47  which handles most of the ugly details.  In addition, a low-level "debug hook
    48  mechanism" is provided for front ends that wish more control over the
    49  process.  The debug hook mechanism is described below, under the
    50  @code{jit_debugger_set_hook} function.
    51  
    52  This debugger implementation requires a threading system to work
    53  successfully.  At least two threads are required, in addition to those of
    54  the program being debugged:
    55  
    56  @enumerate
    57  @item
    58  Event thread which calls @code{jit_debugger_wait_event} to receive
    59  notifications of breakpoints and other interesting events.
    60  
    61  @item
    62  User interface thread which calls functions like @code{jit_debugger_run},
    63  @code{jit_debugger_step}, etc, to control the debug process.
    64  @end enumerate
    65  
    66  These two threads should be set to "unbreakable" with a call to
    67  @code{jit_debugger_set_breakable}.  This prevents them from accidentally
    68  stopping at a breakpoint, which would cause a system deadlock.
    69  Other housekeeping threads, such as a finalization thread, should
    70  also be set to "unbreakable" for the same reason.
    71  
    72  @noindent
    73  Events have the following members:
    74  
    75  @table @code
    76  @item type
    77  The type of event (see the next table for details).
    78  
    79  @item thread
    80  The thread that the event occurred on.
    81  
    82  @item function
    83  The function that the breakpoint occurred within.
    84  
    85  @item data1
    86  @itemx data2
    87  The data values at the breakpoint.  These values are inserted into
    88  the function's code with @code{jit_insn_mark_breakpoint}.
    89  
    90  @item id
    91  The identifier for the breakpoint.
    92  
    93  @item trace
    94  The stack trace corresponding to the location where the breakpoint
    95  occurred.  This value is automatically freed upon the next call
    96  to @code{jit_debugger_wait_event}.  If you wish to preserve the
    97  value, then you must call @code{jit_stack_trace_copy}.
    98  @end table
    99  
   100  @noindent
   101  The following event types are currently supported:
   102  
   103  @table @code
   104  @item JIT_DEBUGGER_TYPE_QUIT
   105  A thread called @code{jit_debugger_quit}, indicating that it wanted the
   106  event thread to terminate.
   107  
   108  @item JIT_DEBUGGER_TYPE_HARD_BREAKPOINT
   109  A thread stopped at a hard breakpoint.  That is, a breakpoint defined
   110  by a call to @code{jit_debugger_add_breakpoint}.
   111  
   112  @item JIT_DEBUGGER_TYPE_SOFT_BREAKPOINT
   113  A thread stopped at a breakpoint that wasn't explicitly defined by
   114  a call to @code{jit_debugger_add_breakpoint}.  This typicaly results
   115  from a call to a "step" function like @code{jit_debugger_step}, where
   116  execution stopped at the next line but there isn't an explicit breakpoint
   117  on that line.
   118  
   119  @item JIT_DEBUGGER_TYPE_USER_BREAKPOINT
   120  A thread stopped because of a call to @code{jit_debugger_break}.
   121  
   122  @item JIT_DEBUGGER_TYPE_ATTACH_THREAD
   123  A thread called @code{jit_debugger_attach_self}.  The @code{data1} field
   124  of the event is set to the value of @code{stop_immediately} for the call.
   125  
   126  @item JIT_DEBUGGER_TYPE_DETACH_THREAD
   127  A thread called @code{jit_debugger_detach_self}.
   128  @end table
   129  
   130  @deftypefun int jit_insn_mark_breakpoint_variable (jit_function_t @var{func}, jit_value_t @var{data1}, jit_value_t @var{data2})
   131  This function is similar to @code{jit_insn_mark_breakpoint} except that values
   132  in @var{data1} and @var{data2} can be computed at runtime. You can use this
   133  function for example to get address of local variable.
   134  @end deftypefun
   135  
   136  @*/
   137  
   138  /*
   139   * Linked event, for the debugger event queue.
   140   */
   141  typedef struct jit_debugger_linked_event
   142  {
   143  	jit_debugger_event_t				event;
   144  	struct jit_debugger_linked_event   *next;
   145  
   146  } jit_debugger_linked_event_t;
   147  
   148  /*
   149   * Run types.
   150   */
   151  #define	JIT_RUN_TYPE_STOPPED		0
   152  #define	JIT_RUN_TYPE_CONTINUE		1
   153  #define	JIT_RUN_TYPE_STEP			2
   154  #define	JIT_RUN_TYPE_NEXT			3
   155  #define	JIT_RUN_TYPE_FINISH			4
   156  #define	JIT_RUN_TYPE_DETACHED		5
   157  
   158  /*
   159   * Information about a thread that is under the control of the debugger.
   160   */
   161  typedef struct jit_debugger_thread
   162  {
   163  	struct jit_debugger_thread *next;
   164  	jit_debugger_thread_id_t	id;
   165  	jit_thread_id_t				native_id;
   166  	int				   volatile	run_type;
   167  	jit_function_t				find_func;
   168  	jit_nint					last_data1;
   169  	jit_nint					last_func_data1;
   170  	int							breakable;
   171  
   172  } *jit_debugger_thread_t;
   173  
   174  /*
   175   * Structure of a debugger instance.
   176   */
   177  struct jit_debugger
   178  {
   179  	jit_monitor_t				  queue_lock;
   180  	jit_monitor_t				  run_lock;
   181  	jit_context_t				  context;
   182  	jit_debugger_linked_event_t * volatile events;
   183  	jit_debugger_linked_event_t * volatile last_event;
   184  };
   185  
   186  /*
   187   * Lock the debugger object.
   188   */
   189  #define	lock_debugger(dbg)		jit_monitor_lock(&((dbg)->run_lock))
   190  
   191  /*
   192   * Unlock the debugger object.
   193   */
   194  #define	unlock_debugger(dbg)	jit_monitor_unlock(&((dbg)->run_lock))
   195  
   196  /*
   197   * Suspend the current thread until it is marked as running again.
   198   * It is assumed that the debugger's monitor lock has been acquired.
   199   */
   200  static void suspend_thread(jit_debugger_t dbg, jit_debugger_thread_t thread)
   201  {
   202  	while(thread->run_type == JIT_RUN_TYPE_STOPPED)
   203  	{
   204  		jit_monitor_wait(&(dbg->run_lock), -1);
   205  	}
   206  }
   207  
   208  /*
   209   * Wake all threads that are waiting on the debugger's monitor.
   210   */
   211  #define	wakeup_all(dbg)		jit_monitor_signal_all(&((dbg)->run_lock))
   212  
   213  /*
   214   * Get the information block for the current thread.
   215   */
   216  static jit_debugger_thread_t get_current_thread(jit_debugger_t dbg)
   217  {
   218  	/* TODO */
   219  	return 0;
   220  }
   221  
   222  /*
   223   * Get the information block for a specific thread.
   224   */
   225  static jit_debugger_thread_t get_specific_thread
   226  		(jit_debugger_t dbg, jit_debugger_thread_id_t thread)
   227  {
   228  	/* TODO */
   229  	return 0;
   230  }
   231  
   232  /*
   233   * Allocate space for a new event on the event queue.
   234   */
   235  #define	alloc_event()		\
   236  		((jit_debugger_event_t *)jit_cnew(jit_debugger_linked_event_t))
   237  
   238  /*
   239   * Add an event that was previously allocated with "alloc_event"
   240   * to a debugger's event queue.
   241   */
   242  static void add_event(jit_debugger_t dbg, jit_debugger_event_t *_event)
   243  {
   244  	jit_debugger_linked_event_t *event = (jit_debugger_linked_event_t *)_event;
   245  	event->next = 0;
   246  	jit_monitor_lock(&(dbg->queue_lock));
   247  	if(dbg->last_event)
   248  	{
   249  		dbg->last_event->next = event;
   250  	}
   251  	else
   252  	{
   253  		dbg->events = event;
   254  	}
   255  	dbg->last_event = event;
   256  	jit_monitor_signal(&(dbg->queue_lock));
   257  	jit_monitor_unlock(&(dbg->queue_lock));
   258  }
   259  
   260  /*@
   261   * @deftypefun int jit_debugging_possible (void)
   262   * Determine if debugging is possible.  i.e. that threading is available
   263   * and compatible with the debugger's requirements.
   264   * @end deftypefun
   265  @*/
   266  int jit_debugging_possible(void)
   267  {
   268  	return JIT_THREADS_SUPPORTED;
   269  }
   270  
   271  /*@
   272   * @deftypefun jit_debugger_t jit_debugger_create (jit_context_t @var{context})
   273   * Create a new debugger instance and attach it to a JIT @var{context}.
   274   * If the context already has a debugger associated with it, then this
   275   * function will return the previous debugger.
   276   * @end deftypefun
   277  @*/
   278  jit_debugger_t jit_debugger_create(jit_context_t context)
   279  {
   280  	jit_debugger_t dbg;
   281  	if(context)
   282  	{
   283  		if(context->debugger)
   284  		{
   285  			return context->debugger;
   286  		}
   287  		dbg = jit_cnew(struct jit_debugger);
   288  		if(!dbg)
   289  		{
   290  			return 0;
   291  		}
   292  		dbg->context = context;
   293  		context->debugger = dbg;
   294  		jit_monitor_create(&(dbg->queue_lock));
   295  		jit_monitor_create(&(dbg->run_lock));
   296  		return dbg;
   297  	}
   298  	else
   299  	{
   300  		return 0;
   301  	}
   302  }
   303  
   304  /*@
   305   * @deftypefun void jit_debugger_destroy (jit_debugger_t @var{dbg})
   306   * Destroy a debugger instance.
   307   * @end deftypefun
   308  @*/
   309  void jit_debugger_destroy(jit_debugger_t dbg)
   310  {
   311  	/* TODO */
   312  }
   313  
   314  /*@
   315   * @deftypefun jit_context_t jit_debugger_get_context (jit_debugger_t @var{dbg})
   316   * Get the JIT context that is associated with a debugger instance.
   317   * @end deftypefun
   318  @*/
   319  jit_context_t jit_debugger_get_context(jit_debugger_t dbg)
   320  {
   321  	if(dbg)
   322  	{
   323  		return dbg->context;
   324  	}
   325  	else
   326  	{
   327  		return 0;
   328  	}
   329  }
   330  
   331  /*@
   332   * @deftypefun jit_debugger_t jit_debugger_from_context (jit_context_t @var{context})
   333   * Get the debugger that is currently associated with a JIT @var{context},
   334   * or NULL if there is no debugger associated with the context.
   335   * @end deftypefun
   336  @*/
   337  jit_debugger_t jit_debugger_from_context(jit_context_t context)
   338  {
   339  	if(context)
   340  	{
   341  		return context->debugger;
   342  	}
   343  	else
   344  	{
   345  		return 0;
   346  	}
   347  }
   348  
   349  /*@
   350   * @deftypefun jit_debugger_thread_id_t jit_debugger_get_self (jit_debugger_t @var{dbg})
   351   * Get the thread identifier associated with the current thread.
   352   * The return values are normally values like 1, 2, 3, etc, allowing
   353   * the user interface to report messages like "thread 3 has stopped
   354   * at a breakpoint".
   355   * @end deftypefun
   356  @*/
   357  jit_debugger_thread_id_t jit_debugger_get_self(jit_debugger_t dbg)
   358  {
   359  	jit_thread_id_t id = jit_thread_self();
   360  	jit_debugger_thread_id_t thread;
   361  	thread = jit_debugger_get_thread(dbg, &id);
   362  	jit_thread_release_self(id);
   363  	return thread;
   364  }
   365  
   366  /*@
   367   * @deftypefun jit_debugger_thread_id_t jit_debugger_get_thread (jit_debugger_t @var{dbg}, const void *@var{native_thread})
   368   * Get the thread identifier for a specific native thread.  The
   369   * @var{native_thread} pointer is assumed to point at a block
   370   * of memory containing a native thread handle.  This would be a
   371   * @code{pthread_t} on Pthreads platforms or a @code{HANDLE}
   372   * on Win32 platforms.  If the native thread has not been seen
   373   * previously, then a new thread identifier is allocated.
   374   * @end deftypefun
   375  @*/
   376  jit_debugger_thread_id_t jit_debugger_get_thread
   377  		(jit_debugger_t dbg, const void *native_thread)
   378  {
   379  	/* TODO */
   380  	return 0;
   381  }
   382  
   383  /*@
   384   * @deftypefun int jit_debugger_get_native_thread (jit_debugger_t @var{dbg}, jit_debugger_thread_id_t @var{thread}, void *@var{native_thread})
   385   * Get the native thread handle associated with a debugger thread identifier.
   386   * Returns non-zero if OK, or zero if the debugger thread identifier is not
   387   * yet associated with a native thread handle.
   388   * @end deftypefun
   389  @*/
   390  int jit_debugger_get_native_thread
   391  		(jit_debugger_t dbg, jit_debugger_thread_id_t thread,
   392  		 void *native_thread)
   393  {
   394  	jit_debugger_thread_t th;
   395  	lock_debugger(dbg);
   396  	th = get_specific_thread(dbg, thread);
   397  	if(th)
   398  	{
   399  		jit_memcpy(native_thread, &(th->native_id), sizeof(th->native_id));
   400  		unlock_debugger(dbg);
   401  		return 1;
   402  	}
   403  	else
   404  	{
   405  		unlock_debugger(dbg);
   406  		return 0;
   407  	}
   408  }
   409  
   410  /*@
   411   * @deftypefun void jit_debugger_set_breakable (jit_debugger_t @var{dbg}, const void *@var{native_thread}, int @var{flag})
   412   * Set a flag that indicates if a native thread can stop at breakpoints.
   413   * If set to 1 (the default), breakpoints will be active on the thread.
   414   * If set to 0, breakpoints will be ignored on the thread.  Typically
   415   * this is used to mark threads associated with the debugger's user
   416   * interface, or the virtual machine's finalization thread, so that they
   417   * aren't accidentally suspended by the debugger (which might cause a
   418   * deadlock).
   419   * @end deftypefun
   420  @*/
   421  void jit_debugger_set_breakable
   422  		(jit_debugger_t dbg, const void *native_thread, int flag)
   423  {
   424  	jit_debugger_thread_t th;
   425  	jit_debugger_thread_id_t id;
   426  	id = jit_debugger_get_thread(dbg, native_thread);
   427  	lock_debugger(dbg);
   428  	th = get_specific_thread(dbg, id);
   429  	if(th)
   430  	{
   431  		th->breakable = flag;
   432  	}
   433  	unlock_debugger(dbg);
   434  }
   435  
   436  /*@
   437   * @deftypefun void jit_debugger_attach_self (jit_debugger_t @var{dbg}, int @var{stop_immediately})
   438   * Attach the current thread to a debugger.  If @var{stop_immediately}
   439   * is non-zero, then the current thread immediately suspends, waiting for
   440   * the user to start it with @code{jit_debugger_run}.  This function is
   441   * typically called in a thread's startup code just before any "real work"
   442   * is performed.
   443   * @end deftypefun
   444  @*/
   445  void jit_debugger_attach_self(jit_debugger_t dbg, int stop_immediately)
   446  {
   447  	jit_debugger_event_t *event;
   448  	jit_debugger_thread_t th;
   449  	lock_debugger(dbg);
   450  	th = get_current_thread(dbg);
   451  	if(th)
   452  	{
   453  		event = alloc_event();
   454  		if(event)
   455  		{
   456  			event->type = JIT_DEBUGGER_TYPE_ATTACH_THREAD;
   457  			event->thread = th->id;
   458  			event->data1 = (jit_nint)stop_immediately;
   459  			add_event(dbg, event);
   460  			th->find_func = 0;
   461  			th->last_data1 = 0;
   462  			th->last_func_data1 = 0;
   463  			if(stop_immediately)
   464  			{
   465  				th->run_type = JIT_RUN_TYPE_STOPPED;
   466  				suspend_thread(dbg, th);
   467  			}
   468  			else
   469  			{
   470  				th->run_type = JIT_RUN_TYPE_CONTINUE;
   471  			}
   472  		}
   473  	}
   474  	unlock_debugger(dbg);
   475  }
   476  
   477  /*@
   478   * @deftypefun void jit_debugger_detach_self (jit_debugger_t @var{dbg})
   479   * Detach the current thread from the debugger.  This is typically
   480   * called just before the thread exits.
   481   * @end deftypefun
   482  @*/
   483  void jit_debugger_detach_self(jit_debugger_t dbg)
   484  {
   485  	jit_debugger_event_t *event;
   486  	jit_debugger_thread_t th;
   487  	lock_debugger(dbg);
   488  	th = get_current_thread(dbg);
   489  	if(th)
   490  	{
   491  		event = alloc_event();
   492  		if(event)
   493  		{
   494  			event->type = JIT_DEBUGGER_TYPE_DETACH_THREAD;
   495  			event->thread = th->id;
   496  			add_event(dbg, event);
   497  			th->run_type = JIT_RUN_TYPE_DETACHED;
   498  		}
   499  	}
   500  	unlock_debugger(dbg);
   501  }
   502  
   503  /*@
   504   * @deftypefun int jit_debugger_wait_event (jit_debugger_t @var{dbg}, jit_debugger_event_t *@var{event}, jit_nint @var{timeout})
   505   * Wait for the next debugger event to arrive.  Debugger events typically
   506   * indicate breakpoints that have occurred.  The @var{timeout} is in
   507   * milliseconds, or -1 for an infinite timeout period.  Returns non-zero
   508   * if an event has arrived, or zero on timeout.
   509   * @end deftypefun
   510  @*/
   511  int jit_debugger_wait_event
   512  		(jit_debugger_t dbg, jit_debugger_event_t *event, jit_int timeout)
   513  {
   514  	jit_debugger_linked_event_t *levent;
   515  	jit_monitor_lock(&(dbg->queue_lock));
   516  	if((levent = dbg->events) == 0)
   517  	{
   518  		if(!jit_monitor_wait(&(dbg->queue_lock), timeout))
   519  		{
   520  			jit_monitor_unlock(&(dbg->queue_lock));
   521  			return 0;
   522  		}
   523  		levent = dbg->events;
   524  	}
   525  	*event = levent->event;
   526  	dbg->events = levent->next;
   527  	if(!(levent->next))
   528  	{
   529  		dbg->last_event = 0;
   530  	}
   531  	jit_free(levent);
   532  	jit_monitor_unlock(&(dbg->queue_lock));
   533  	return 1;
   534  }
   535  
   536  /*@
   537   * @deftypefun jit_debugger_breakpoint_id_t jit_debugger_add_breakpoint (jit_debugger_t @var{dbg}, jit_debugger_breakpoint_info_t @var{info})
   538   * Add a hard breakpoint to a debugger instance.  The @var{info} structure
   539   * defines the conditions under which the breakpoint should fire.
   540   * The fields of @var{info} are as follows:
   541   *
   542   * @table @code
   543   * @item flags
   544   * Flags that indicate which of the following fields should be matched.
   545   * If a flag is not present, then all possible values of the field will match.
   546   * Valid flags are @code{JIT_DEBUGGER_FLAG_THREAD},
   547   * @code{JIT_DEBUGGER_FLAG_FUNCTION}, @code{JIT_DEBUGGER_FLAG_DATA1},
   548   * and @code{JIT_DEBUGGER_FLAG_DATA2}.
   549   *
   550   * @item thread
   551   * The thread to match against, if @code{JIT_DEBUGGER_FLAG_THREAD} is set.
   552   *
   553   * @item function
   554   * The function to match against, if @code{JIT_DEBUGGER_FLAG_FUNCTION} is set.
   555   *
   556   * @item data1
   557   * The @code{data1} value to match against, if @code{JIT_DEBUGGER_FLAG_DATA1}
   558   * is set.
   559   *
   560   * @item data2
   561   * The @code{data2} value to match against, if @code{JIT_DEBUGGER_FLAG_DATA2}
   562   * is set.
   563   * @end table
   564   *
   565   * The following special values for @code{data1} are recommended for marking
   566   * breakpoint locations with @code{jit_insn_mark_breakpoint}:
   567   *
   568   * @table @code
   569   * @item JIT_DEBUGGER_DATA1_LINE
   570   * Breakpoint location that corresponds to a source line.  This is used
   571   * to determine where to continue to upon a "step".
   572   *
   573   * @item JIT_DEBUGGER_DATA1_ENTER
   574   * Breakpoint location that corresponds to the start of a function.
   575   *
   576   * @item JIT_DEBUGGER_DATA1_LEAVE
   577   * Breakpoint location that corresponds to the end of a function, just
   578   * prior to a @code{return} statement.  This is used to determine where
   579   * to continue to upon a "finish".
   580   *
   581   * @item JIT_DEBUGGER_DATA1_THROW
   582   * Breakpoint location that corresponds to an exception throw.
   583   * @end table
   584   * @end deftypefun
   585  @*/
   586  jit_debugger_breakpoint_id_t jit_debugger_add_breakpoint
   587  		(jit_debugger_t dbg, jit_debugger_breakpoint_info_t info)
   588  {
   589  	/* TODO */
   590  	return 0;
   591  }
   592  
   593  /*@
   594   * @deftypefun void jit_debugger_remove_breakpoint (jit_debugger_t @var{dbg}, jit_debugger_breakpoint_id_t @var{id})
   595   * Remove a previously defined breakpoint from a debugger instance.
   596   * @end deftypefun
   597  @*/
   598  void jit_debugger_remove_breakpoint
   599  		(jit_debugger_t dbg, jit_debugger_breakpoint_id_t id)
   600  {
   601  	/* TODO */
   602  }
   603  
   604  /*@
   605   * @deftypefun void jit_debugger_remove_all_breakpoints (jit_debugger_t @var{dbg})
   606   * Remove all breakpoints from a debugger instance.
   607   * @end deftypefun
   608  @*/
   609  void jit_debugger_remove_all_breakpoints(jit_debugger_t dbg)
   610  {
   611  	/* TODO */
   612  }
   613  
   614  /*@
   615   * @deftypefun int jit_debugger_is_alive (jit_debugger_t @var{dbg}, jit_debugger_thread_id_t @var{thread})
   616   * Determine if a particular thread is still alive.
   617   * @end deftypefun
   618  @*/
   619  int jit_debugger_is_alive(jit_debugger_t dbg, jit_debugger_thread_id_t thread)
   620  {
   621  	/* TODO */
   622  	return 1;
   623  }
   624  
   625  /*@
   626   * @deftypefun int jit_debugger_is_running (jit_debugger_t @var{dbg}, jit_debugger_thread_id_t @var{thread})
   627   * Determine if a particular thread is currently running (non-zero) or
   628   * stopped (zero).
   629   * @end deftypefun
   630  @*/
   631  int jit_debugger_is_running(jit_debugger_t dbg, jit_debugger_thread_id_t thread)
   632  {
   633  	jit_debugger_thread_t th;
   634  	int flag = 0;
   635  	lock_debugger(dbg);
   636  	th = get_specific_thread(dbg, thread);
   637  	if(th)
   638  	{
   639  		flag = (th->run_type != JIT_RUN_TYPE_STOPPED);
   640  	}
   641  	unlock_debugger(dbg);
   642  	return flag;
   643  }
   644  
   645  /*@
   646   * @deftypefun void jit_debugger_run (jit_debugger_t @var{dbg}, jit_debugger_thread_id_t @var{thread})
   647   * Start the specified thread running, or continue from the last breakpoint.
   648   *
   649   * This function, and the others that follow, sends a request to the specified
   650   * thread and then returns to the caller immediately.
   651   * @end deftypefun
   652  @*/
   653  void jit_debugger_run(jit_debugger_t dbg, jit_debugger_thread_id_t thread)
   654  {
   655  	jit_debugger_thread_t th;
   656  	lock_debugger(dbg);
   657  	th = get_specific_thread(dbg, thread);
   658  	if(th && th->run_type == JIT_RUN_TYPE_STOPPED)
   659  	{
   660  		th->run_type = JIT_RUN_TYPE_CONTINUE;
   661  		wakeup_all(dbg);
   662  	}
   663  	unlock_debugger(dbg);
   664  }
   665  
   666  /*@
   667   * @deftypefun void jit_debugger_step (jit_debugger_t @var{dbg}, jit_debugger_thread_id_t @var{thread})
   668   * Step over a single line of code.  If the line performs a method call,
   669   * then this will step into the call.  The request will be ignored if
   670   * the thread is currently running.
   671   * @end deftypefun
   672  @*/
   673  void jit_debugger_step(jit_debugger_t dbg, jit_debugger_thread_id_t thread)
   674  {
   675  	jit_debugger_thread_t th;
   676  	lock_debugger(dbg);
   677  	th = get_specific_thread(dbg, thread);
   678  	if(th && th->run_type == JIT_RUN_TYPE_STOPPED)
   679  	{
   680  		th->run_type = JIT_RUN_TYPE_STEP;
   681  		wakeup_all(dbg);
   682  	}
   683  	unlock_debugger(dbg);
   684  }
   685  
   686  /*@
   687   * @deftypefun void jit_debugger_next (jit_debugger_t @var{dbg}, jit_debugger_thread_id_t @var{thread})
   688   * Step over a single line of code but do not step into method calls.
   689   * The request will be ignored if the thread is currently running.
   690   * @end deftypefun
   691  @*/
   692  void jit_debugger_next(jit_debugger_t dbg, jit_debugger_thread_id_t thread)
   693  {
   694  	jit_debugger_thread_t th;
   695  	lock_debugger(dbg);
   696  	th = get_specific_thread(dbg, thread);
   697  	if(th && th->run_type == JIT_RUN_TYPE_STOPPED)
   698  	{
   699  		th->run_type = JIT_RUN_TYPE_NEXT;
   700  		wakeup_all(dbg);
   701  	}
   702  	unlock_debugger(dbg);
   703  }
   704  
   705  /*@
   706   * @deftypefun void jit_debugger_finish (jit_debugger_t @var{dbg}, jit_debugger_thread_id_t @var{thread})
   707   * Keep running until the end of the current function.  The request will
   708   * be ignored if the thread is currently running.
   709   * @end deftypefun
   710  @*/
   711  void jit_debugger_finish(jit_debugger_t dbg, jit_debugger_thread_id_t thread)
   712  {
   713  	jit_debugger_thread_t th;
   714  	lock_debugger(dbg);
   715  	th = get_specific_thread(dbg, thread);
   716  	if(th && th->run_type == JIT_RUN_TYPE_STOPPED)
   717  	{
   718  		th->run_type = JIT_RUN_TYPE_FINISH;
   719  		wakeup_all(dbg);
   720  	}
   721  	unlock_debugger(dbg);
   722  }
   723  
   724  /*@
   725   * @deftypefun void jit_debugger_break (jit_debugger_t @var{dbg})
   726   * Force an explicit user breakpoint at the current location within the
   727   * current thread.  Control returns to the caller when the debugger
   728   * calls one of the above "run" or "step" functions in another thread.
   729   * @end deftypefun
   730  @*/
   731  void jit_debugger_break(jit_debugger_t dbg)
   732  {
   733  	jit_debugger_event_t *event;
   734  	jit_debugger_thread_t th;
   735  	lock_debugger(dbg);
   736  	th = get_current_thread(dbg);
   737  	if(th && th->breakable)
   738  	{
   739  		event = alloc_event();
   740  		if(event)
   741  		{
   742  			th->run_type = JIT_RUN_TYPE_STOPPED;
   743  			th->find_func = 0;
   744  			th->last_data1 = 0;
   745  			th->last_func_data1 = 0;
   746  			event->type = JIT_DEBUGGER_TYPE_USER_BREAKPOINT;
   747  			event->thread = th->id;
   748  			event->trace = jit_exception_get_stack_trace();
   749  			add_event(dbg, event);
   750  			suspend_thread(dbg, th);
   751  		}
   752  	}
   753  	unlock_debugger(dbg);
   754  }
   755  
   756  /*@
   757   * @deftypefun void jit_debugger_quit (jit_debugger_t @var{dbg})
   758   * Sends a request to the thread that called @code{jit_debugger_wait_event}
   759   * indicating that the debugger should quit.
   760   * @end deftypefun
   761  @*/
   762  void jit_debugger_quit(jit_debugger_t dbg)
   763  {
   764  	jit_debugger_event_t *event;
   765  	lock_debugger(dbg);
   766  	event = alloc_event();
   767  	if(event)
   768  	{
   769  		event->type = JIT_DEBUGGER_TYPE_QUIT;
   770  		add_event(dbg, event);
   771  	}
   772  	unlock_debugger(dbg);
   773  }
   774  
   775  /*@
   776   * @deftypefun jit_debugger_hook_func jit_debugger_set_hook (jit_context_t @var{context}, jit_debugger_hook_func @var{hook})
   777   * Set a debugger hook on a JIT context.  Returns the previous hook.
   778   *
   779   * Debug hooks are a very low-level breakpoint mechanism.  Upon reaching each
   780   * breakpoint in a function, a user-supplied hook function is called.
   781   * It is up to the hook function to decide whether to stop execution
   782   * or to ignore the breakpoint.  The hook function has the following
   783   * prototype:
   784   *
   785   * @example
   786   * void hook(jit_function_t func, jit_nint data1, jit_nint data2);
   787   * @end example
   788   *
   789   * The @code{func} argument indicates the function that the breakpoint
   790   * occurred within.  The @code{data1} and @code{data2} arguments are
   791   * those supplied to @code{jit_insn_mark_breakpoint}.  The debugger can use
   792   * these values to indicate information about the breakpoint's type
   793   * and location.
   794   *
   795   * Hook functions can be used for other purposes besides breakpoint
   796   * debugging.  For example, a program could be instrumented with hooks
   797   * that tally up the number of times that each function is called,
   798   * or which profile the amount of time spent in each function.
   799   *
   800   * By convention, @code{data1} values less than 10000 are intended for
   801   * use by user-defined hook functions.  Values of 10000 and greater are
   802   * reserved for the full-blown debugger system described earlier.
   803   * @end deftypefun
   804  @*/
   805  jit_debugger_hook_func jit_debugger_set_hook
   806  		(jit_context_t context, jit_debugger_hook_func hook)
   807  {
   808  	jit_debugger_hook_func prev;
   809  	if(context)
   810  	{
   811  		prev = context->debug_hook;
   812  		context->debug_hook = hook;
   813  		return prev;
   814  	}
   815  	else
   816  	{
   817  		return 0;
   818  	}
   819  }
   820  
   821  void _jit_debugger_hook(jit_function_t func, jit_nint data1, jit_nint data2)
   822  {
   823  	jit_context_t context;
   824  	jit_debugger_t dbg;
   825  	jit_debugger_thread_t th;
   826  	jit_debugger_event_t *event;
   827  	int stop;
   828  
   829  	/* Find the context and look for a user-supplied debug hook */
   830  	context = func->context;
   831  	if(context->debug_hook)
   832  	{
   833  		(*(context->debug_hook))(func, data1, data2);
   834  	}
   835  
   836  	/* Ignore breakpoints with data1 values less than 10000.  These are
   837  	   presumed to be handled by a user-supplied debug hook instead */
   838  	if(data1 < JIT_DEBUGGER_DATA1_FIRST)
   839  	{
   840  		return;
   841  	}
   842  
   843  	/* Determine if there is a debugger attached to the context */
   844  	dbg = context->debugger;
   845  	if(!dbg)
   846  	{
   847  		return;
   848  	}
   849  
   850  	/* Lock down the debugger while we do this */
   851  	lock_debugger(dbg);
   852  
   853  	/* Get the current thread's information block */
   854  	th = get_current_thread(dbg);
   855  	if(!th || !(th->breakable))
   856  	{
   857  		unlock_debugger(dbg);
   858  		return;
   859  	}
   860  
   861  	/* Determine if there is a hard breakpoint at this location */
   862  	/* TODO */
   863  
   864  	/* Determine if we are looking for a soft breakpoint */
   865  	stop = 0;
   866  	switch(th->run_type)
   867  	{
   868  		case JIT_RUN_TYPE_STEP:
   869  		{
   870  			/* Stop at all breakpoints */
   871  			stop = 1;
   872  		}
   873  		break;
   874  
   875  		case JIT_RUN_TYPE_NEXT:
   876  		{
   877  			/* Stop only if we are in the same function as the last stopping
   878  			   point, or if we might have already left the function */
   879  			if(func == th->find_func || th->find_func == 0 ||
   880  			   th->last_func_data1 == JIT_DEBUGGER_DATA1_LEAVE ||
   881  			   th->last_data1 == JIT_DEBUGGER_DATA1_THROW)
   882  			{
   883  				stop = 1;
   884  			}
   885  			if(func == th->find_func)
   886  			{
   887  				th->last_func_data1 = data1;
   888  			}
   889  		}
   890  		break;
   891  
   892  		case JIT_RUN_TYPE_FINISH:
   893  		{
   894  			/* Stop if we are at a leave point, or we saw an exception */
   895  			if((func == th->find_func && data1 == JIT_DEBUGGER_DATA1_LEAVE) ||
   896  			   th->last_data1 == JIT_DEBUGGER_DATA1_THROW ||
   897  			   th->find_func == 0)
   898  			{
   899  				stop = 1;
   900  			}
   901  		}
   902  		break;
   903  	}
   904  	th->last_data1 = data1;
   905  
   906  	/* Do we need to stop the thread at this breakpoint? */
   907  	if(stop)
   908  	{
   909  		event = alloc_event();
   910  		if(event)
   911  		{
   912  			th->run_type = JIT_RUN_TYPE_STOPPED;
   913  			th->find_func = func;
   914  			th->last_func_data1 = data1;
   915  			event->type = JIT_DEBUGGER_TYPE_SOFT_BREAKPOINT;
   916  			event->thread = th->id;
   917  			event->function = func;
   918  			event->data1 = data1;
   919  			event->data2 = data2;
   920  			event->trace = jit_exception_get_stack_trace();
   921  			add_event(dbg, event);
   922  			suspend_thread(dbg, th);
   923  		}
   924  	}
   925  
   926  	/* Unlock and exit */
   927  	unlock_debugger(dbg);
   928  }