This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch 3/3] bpstat_what removal


Hi,

the simple idea is to inline bpstat_what into handle_inferior_event.  This
removes enum bpstat_what_main_action and struct bpstat_what currently acting
just as an interface between these two functions.

solib_add() needs to stay delayed as it has too disturbing effect on the
content of stop_bpstat.

breakpoint_type_name is there just for DEBUG_INFRUN.


Thanks,
Jan


gdb/
2010-05-03  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* breakpoint.c (bpstat_what): Remove.
	(breakpoint_type_name): New.
	* breakpoint.h (enum bpstat_what_main_action, struct bpstat_what)
	(bpstat_what): Remove.
	(breakpoint_type_name): New prototype.
	* infrun.c (handle_inferior_event): Clear frame and gdbarch before
	deciding what action to take.  New variables bs, print_frame_max,
	stop_step_max, perform_max and perform_shlib.  Replace the bpstat_what
	call by new inlined deciding code.  Reinitialize even gdbarch when
	frame gets reinitialized.

gdb/testsuite/
2010-05-03  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* break-solib-event.exp: New.

--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -4161,250 +4161,6 @@ bpstat_stop_status (struct address_space *aspace,
   return root_bs->next;
 }
 
-/* Tell what to do about this bpstat.  */
-struct bpstat_what
-bpstat_what (bpstat bs)
-{
-  /* Classify each bpstat as one of the following.  */
-  enum class
-    {
-      /* This bpstat element has no effect on the main_action.  */
-      no_effect = 0,
-
-      /* There was a watchpoint, stop but don't print.  */
-      wp_silent,
-
-      /* There was a watchpoint, stop and print.  */
-      wp_noisy,
-
-      /* There was a breakpoint but we're not stopping.  */
-      bp_nostop,
-
-      /* There was a breakpoint, stop but don't print.  */
-      bp_silent,
-
-      /* There was a breakpoint, stop and print.  */
-      bp_noisy,
-
-      /* We hit the longjmp breakpoint.  */
-      long_jump,
-
-      /* We hit the longjmp_resume breakpoint.  */
-      long_resume,
-
-      /* We hit the step_resume breakpoint.  */
-      step_resume,
-
-      /* We hit the shared library event breakpoint.  */
-      shlib_event,
-
-      /* We hit the jit event breakpoint.  */
-      jit_event,
-
-      /* This is just used to count how many enums there are.  */
-      class_last
-    };
-
-  /* Here is the table which drives this routine.  So that we can
-     format it pretty, we define some abbreviations for the
-     enum bpstat_what codes.  */
-#define kc BPSTAT_WHAT_KEEP_CHECKING
-#define ss BPSTAT_WHAT_STOP_SILENT
-#define sn BPSTAT_WHAT_STOP_NOISY
-#define sgl BPSTAT_WHAT_SINGLE
-#define slr BPSTAT_WHAT_SET_LONGJMP_RESUME
-#define clr BPSTAT_WHAT_CLEAR_LONGJMP_RESUME
-#define sr BPSTAT_WHAT_STEP_RESUME
-#define shl BPSTAT_WHAT_CHECK_SHLIBS
-#define jit BPSTAT_WHAT_CHECK_JIT
-
-/* "Can't happen."  Might want to print an error message.
-   abort() is not out of the question, but chances are GDB is just
-   a bit confused, not unusable.  */
-#define err BPSTAT_WHAT_STOP_NOISY
-
-  /* Given an old action and a class, come up with a new action.  */
-  /* One interesting property of this table is that wp_silent is the same
-     as bp_silent and wp_noisy is the same as bp_noisy.  That is because
-     after stopping, the check for whether to step over a breakpoint
-     (BPSTAT_WHAT_SINGLE type stuff) is handled in proceed() without
-     reference to how we stopped.  We retain separate wp_silent and
-     bp_silent codes in case we want to change that someday. 
-
-     Another possibly interesting property of this table is that
-     there's a partial ordering, priority-like, of the actions.  Once
-     you've decided that some action is appropriate, you'll never go
-     back and decide something of a lower priority is better.  The
-     ordering is:
-
-     kc   < jit clr sgl shl slr sn sr ss
-     sgl  < jit shl slr sn sr ss
-     slr  < jit err shl sn sr ss
-     clr  < jit err shl sn sr ss
-     ss   < jit shl sn sr
-     sn   < jit shl sr
-     jit  < shl sr
-     shl  < sr
-     sr   <
-
-     What I think this means is that we don't need a damned table
-     here.  If you just put the rows and columns in the right order,
-     it'd look awfully regular.  We could simply walk the bpstat list
-     and choose the highest priority action we find, with a little
-     logic to handle the 'err' cases.  */
-
-  /* step_resume entries: a step resume breakpoint overrides another
-     breakpoint of signal handling (see comment in wait_for_inferior
-     at where we set the step_resume breakpoint).  */
-
-  static const enum bpstat_what_main_action
-    table[(int) class_last][(int) BPSTAT_WHAT_LAST] =
-  {
-  /*                              old action */
-  /*               kc   ss   sn   sgl  slr  clr  sr  shl  jit */
-/* no_effect */   {kc,  ss,  sn,  sgl, slr, clr, sr, shl, jit},
-/* wp_silent */   {ss,  ss,  sn,  ss,  ss,  ss,  sr, shl, jit},
-/* wp_noisy */    {sn,  sn,  sn,  sn,  sn,  sn,  sr, shl, jit},
-/* bp_nostop */   {sgl, ss,  sn,  sgl, slr, slr, sr, shl, jit},
-/* bp_silent */   {ss,  ss,  sn,  ss,  ss,  ss,  sr, shl, jit},
-/* bp_noisy */    {sn,  sn,  sn,  sn,  sn,  sn,  sr, shl, jit},
-/* long_jump */   {slr, ss,  sn,  slr, slr, err, sr, shl, jit},
-/* long_resume */ {clr, ss,  sn,  err, err, err, sr, shl, jit},
-/* step_resume */ {sr,  sr,  sr,  sr,  sr,  sr,  sr, sr,  sr },
-/* shlib */       {shl, shl, shl, shl, shl, shl, sr, shl, shl},
-/* jit_event */   {jit, jit, jit, jit, jit, jit, sr, jit, jit}
-  };
-
-#undef kc
-#undef ss
-#undef sn
-#undef sgl
-#undef slr
-#undef clr
-#undef err
-#undef sr
-#undef ts
-#undef shl
-#undef jit
-  enum bpstat_what_main_action current_action = BPSTAT_WHAT_KEEP_CHECKING;
-  struct bpstat_what retval;
-
-  retval.call_dummy = STOP_NONE;
-  for (; bs != NULL; bs = bs->next)
-    {
-      enum class bs_class = no_effect;
-      if (bs->breakpoint_at == NULL)
-	/* I suspect this can happen if it was a momentary breakpoint
-	   which has since been deleted.  */
-	continue;
-      if (bs->breakpoint_at->owner == NULL)
-	bs_class = bp_nostop;
-      else
-      switch (bs->breakpoint_at->owner->type)
-	{
-	case bp_none:
-	  continue;
-
-	case bp_breakpoint:
-	case bp_hardware_breakpoint:
-	case bp_until:
-	case bp_finish:
-	  if (bs->stop)
-	    {
-	      if (bs->print)
-		bs_class = bp_noisy;
-	      else
-		bs_class = bp_silent;
-	    }
-	  else
-	    bs_class = bp_nostop;
-	  break;
-	case bp_watchpoint:
-	case bp_hardware_watchpoint:
-	case bp_read_watchpoint:
-	case bp_access_watchpoint:
-	  if (bs->stop)
-	    {
-	      if (bs->print)
-		bs_class = wp_noisy;
-	      else
-		bs_class = wp_silent;
-	    }
-	  else
-	    /* There was a watchpoint, but we're not stopping. 
-	       This requires no further action.  */
-	    bs_class = no_effect;
-	  break;
-	case bp_longjmp:
-	  bs_class = long_jump;
-	  break;
-	case bp_longjmp_resume:
-	  bs_class = long_resume;
-	  break;
-	case bp_step_resume:
-	  if (bs->stop)
-	    {
-	      bs_class = step_resume;
-	    }
-	  else
-	    /* It is for the wrong frame.  */
-	    bs_class = bp_nostop;
-	  break;
-	case bp_watchpoint_scope:
-	  bs_class = bp_nostop;
-	  break;
-	case bp_shlib_event:
-	  bs_class = shlib_event;
-	  break;
-	case bp_jit_event:
-	  bs_class = jit_event;
-	  break;
-	case bp_thread_event:
-	case bp_overlay_event:
-	case bp_longjmp_master:
-	case bp_std_terminate_master:
-	  bs_class = bp_nostop;
-	  break;
-	case bp_catchpoint:
-	  if (bs->stop)
-	    {
-	      if (bs->print)
-		bs_class = bp_noisy;
-	      else
-		bs_class = bp_silent;
-	    }
-	  else
-	    /* There was a catchpoint, but we're not stopping.  
-	       This requires no further action.  */
-	    bs_class = no_effect;
-	  break;
-	case bp_call_dummy:
-	  /* Make sure the action is stop (silent or noisy),
-	     so infrun.c pops the dummy frame.  */
-	  bs_class = bp_silent;
-	  retval.call_dummy = STOP_STACK_DUMMY;
-	  break;
-	case bp_std_terminate:
-	  /* Make sure the action is stop (silent or noisy),
-	     so infrun.c pops the dummy frame.  */
-	  bs_class = bp_silent;
-	  retval.call_dummy = STOP_STD_TERMINATE;
-	  break;
-	case bp_tracepoint:
-	case bp_fast_tracepoint:
-	  /* Tracepoint hits should not be reported back to GDB, and
-	     if one got through somehow, it should have been filtered
-	     out already.  */
-	  internal_error (__FILE__, __LINE__,
-			  _("bpstat_what: tracepoint encountered"));
-	  break;
-	}
-      current_action = table[(int) bs_class][(int) current_action];
-    }
-  retval.main_action = current_action;
-  return retval;
-}
-
 /* Nonzero if we should step constantly (e.g. watchpoints on machines
    without hardware support).  This isn't related to a specific bpstat,
    just to things like whether watchpoints are set.  */
@@ -10999,6 +10755,65 @@ save_command (char *arg, int from_tty)
   help_list (save_cmdlist, "save ", -1, gdb_stdout);
 }
 
+const char *
+breakpoint_type_name (enum bptype bptype)
+{
+  switch (bptype)
+    {
+    case bp_none:
+      return "bp_none";
+    case bp_breakpoint:
+      return "bp_breakpoint";
+    case bp_hardware_breakpoint:
+      return "bp_hardware_breakpoint";
+    case bp_until:
+      return "bp_until";
+    case bp_finish:
+      return "bp_finish";
+    case bp_watchpoint:
+      return "bp_watchpoint";
+    case bp_hardware_watchpoint:
+      return "bp_hardware_watchpoint";
+    case bp_read_watchpoint:
+      return "bp_read_watchpoint";
+    case bp_access_watchpoint:
+      return "bp_access_watchpoint";
+    case bp_longjmp:
+      return "bp_longjmp";
+    case bp_longjmp_resume:
+      return "bp_longjmp_resume";
+    case bp_step_resume:
+      return "bp_step_resume";
+    case bp_watchpoint_scope:
+      return "bp_watchpoint_scope";
+    case bp_call_dummy:
+      return "bp_call_dummy";
+    case bp_std_terminate:
+      return "bp_std_terminate";
+    case bp_shlib_event:
+      return "bp_shlib_event";
+    case bp_thread_event:
+      return "bp_thread_event";
+    case bp_overlay_event:
+      return "bp_overlay_event";
+    case bp_longjmp_master:
+      return "bp_longjmp_master";
+    case bp_std_terminate_master:
+      return "bp_std_terminate_master";
+    case bp_catchpoint:
+      return "bp_catchpoint";
+    case bp_tracepoint:
+      return "bp_tracepoint";
+    case bp_fast_tracepoint:
+      return "bp_fast_tracepoint";
+    case bp_jit_event:
+      return "bp_jit_event";
+    }
+  internal_error (__FILE__, __LINE__, _("Invalid breakpoint type %d"),
+		  (int) bptype);
+  return NULL;
+}
+
 void
 _initialize_breakpoint (void)
 {
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -561,58 +561,6 @@ extern bpstat bpstat_copy (bpstat);
 extern bpstat bpstat_stop_status (struct address_space *aspace,
 				  CORE_ADDR pc, ptid_t ptid);
 
-/* This bpstat_what stuff tells wait_for_inferior what to do with a
-   breakpoint (a challenging task).  */
-
-enum bpstat_what_main_action
-  {
-    /* Perform various other tests; that is, this bpstat does not
-       say to perform any action (e.g. failed watchpoint and nothing
-       else).  */
-    BPSTAT_WHAT_KEEP_CHECKING,
-
-    /* Rather than distinguish between noisy and silent stops here, it
-       might be cleaner to have bpstat_print make that decision (also
-       taking into account stop_print_frame and source_only).  But the
-       implications are a bit scary (interaction with auto-displays, etc.),
-       so I won't try it.  */
-
-    /* Stop silently.  */
-    BPSTAT_WHAT_STOP_SILENT,
-
-    /* Stop and print.  */
-    BPSTAT_WHAT_STOP_NOISY,
-
-    /* Remove breakpoints, single step once, then put them back in and
-       go back to what we were doing.  It's possible that this should be
-       removed from the main_action and put into a separate field, to more
-       cleanly handle BPSTAT_WHAT_CLEAR_LONGJMP_RESUME_SINGLE.  */
-    BPSTAT_WHAT_SINGLE,
-
-    /* Set longjmp_resume breakpoint, remove all other breakpoints,
-       and continue.  The "remove all other breakpoints" part is required
-       if we are also stepping over another breakpoint as well as doing
-       the longjmp handling.  */
-    BPSTAT_WHAT_SET_LONGJMP_RESUME,
-
-    /* Clear longjmp_resume breakpoint, then handle as
-       BPSTAT_WHAT_KEEP_CHECKING.  */
-    BPSTAT_WHAT_CLEAR_LONGJMP_RESUME,
-
-    /* Clear step resume breakpoint, and keep checking.  */
-    BPSTAT_WHAT_STEP_RESUME,
-
-    /* Check the dynamic linker's data structures for new libraries, then
-       keep checking.  */
-    BPSTAT_WHAT_CHECK_SHLIBS,
-
-    /* Check for new JITed code.  */
-    BPSTAT_WHAT_CHECK_JIT,
-
-    /* This is just used to keep track of how many enums there are.  */
-    BPSTAT_WHAT_LAST
-  };
-
 /* An enum indicating the kind of "stack dummy" stop.  This is a bit
    of a misnomer because only one kind of truly a stack dummy.  */
 enum stop_stack_kind
@@ -627,17 +575,6 @@ enum stop_stack_kind
     STOP_STD_TERMINATE
   };
 
-struct bpstat_what
-  {
-    enum bpstat_what_main_action main_action;
-
-    /* Did we hit a call dummy breakpoint?  This only goes with a main_action
-       of BPSTAT_WHAT_STOP_SILENT or BPSTAT_WHAT_STOP_NOISY (the concept of
-       continuing from a call dummy without popping the frame is not a
-       useful one).  */
-    enum stop_stack_kind call_dummy;
-  };
-
 /* The possible return values for print_bpstat, print_it_normal, print_it_done,
    print_it_noop.  bpstat_print depends on ther ordering where each item is an
    information subset of the previous one.  */
@@ -650,9 +587,6 @@ enum print_stop_action
     PRINT_UNKNOWN
   };
 
-/* Tell what to do about this bpstat.  */
-struct bpstat_what bpstat_what (bpstat);
-
 /* Find the bpstat associated with a breakpoint.  NULL otherwise. */
 bpstat bpstat_find_breakpoint (bpstat, struct breakpoint *);
 
@@ -1050,4 +984,6 @@ extern void check_tracepoint_command (char *line, void *closure);
 extern void start_rbreak_breakpoints (void);
 extern void end_rbreak_breakpoints (void);
 
+extern const char *breakpoint_type_name (enum bptype bptype);
+
 #endif /* !defined (BREAKPOINT_H) */
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -3947,185 +3947,357 @@ process_event_stop_test:
       return;
     }
 
+  /* Breakpoints may get deleted and created in the block below.  It calls
+     reinit_frame_cache thus invalidating current_frame.  In this block one
+     needs to explicitly get_current_frame.  */
+  frame = NULL;
+  gdbarch = NULL;
+
   /* Handle cases caused by hitting a breakpoint.  */
   {
-    CORE_ADDR jmp_buf_pc;
-    struct bpstat_what what;
-
-    what = bpstat_what (ecs->event_thread->stop_bpstat);
-
-    if (what.call_dummy)
+    bpstat bs;
+    enum print_frame
       {
-	stop_stack_dummy = what.call_dummy;
+	/* pf_default is pf_yes.  */
+	pf_default,
+	/* stop_print_frame value 0.  */
+	pf_no,
+	/* stop_print_frame value 1.  */
+	pf_yes,
       }
-
-    switch (what.main_action)
+    print_frame_max = pf_default;
+    enum stop_step
       {
-      case BPSTAT_WHAT_SET_LONGJMP_RESUME:
-	/* If we hit the breakpoint at longjmp while stepping, we
-	   install a momentary breakpoint at the target of the
-	   jmp_buf.  */
-
-	if (debug_infrun)
-	  fprintf_unfiltered (gdb_stdlog,
-			      "infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME\n");
-
-	ecs->event_thread->stepping_over_breakpoint = 1;
-
-	if (!gdbarch_get_longjmp_target_p (gdbarch)
-	    || !gdbarch_get_longjmp_target (gdbarch, frame, &jmp_buf_pc))
+	/* ss_default is ss_print_yes.  */
+        ss_default,
+	/* ecs->event_thread->stop_step value 1.  */
+	ss_print_no,
+	/* ecs->event_thread->stop_step value 0.  */
+	ss_print_yes,
+      }
+    stop_step_max = ss_default;
+    enum perform
+      {
+        pe_undef,
+	/* Break from this block and check other possibilities why to stop.  */
+	pe_check_more,
+	/* Call stop_stepping (ecs).  */
+	pe_stop,
+	/* Like pe_stop but also print_stop_reason (END_STEPPING_RANGE, 0).  */
+	pe_stop_end_range,
+	/* Call keep_going (ecs) and return without breaking from this block
+	   and checking other possibilities why to stop.  Some operations need
+	   to finish before an already stepped on breakpoint is displayed to
+	   the user.  */
+	pe_going,
+      }
+    perform_max = pe_check_more;
+    /* solib_add may call breakpoint_re_set which would clear many
+       BREAKPOINT_AT entries still going to be processed.  breakpoint_re_set
+       does not keep the same bp_location's even if they actually do not
+       change.  */
+    int perform_shlib = 0;
+
+    for (bs = ecs->event_thread->stop_bpstat; bs != NULL; bs = bs->next)
+      {
+	/* Decisions for this specific BS, they get mapped to their *_max
+	   variants at the end of this BS processing.  */
+	enum print_frame print_frame = pf_default;
+	enum stop_step stop_step = ss_default;
+	enum perform perform = pe_undef;
+	enum bptype bptype;
+
+	if (bs->breakpoint_at == NULL)
 	  {
-	    if (debug_infrun)
-	      fprintf_unfiltered (gdb_stdlog, "\
-infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
-	    keep_going (ecs);
-	    return;
+	    /* I suspect this can happen if it was a momentary breakpoint
+	       which has since been deleted.  */
+	    bptype = bp_none;
 	  }
+	else if (bs->breakpoint_at->owner == NULL)
+	  {
+	    ecs->event_thread->stepping_over_breakpoint = 1;
+	    bptype = bp_none;
+	  }
+	else
+	  bptype = bs->breakpoint_at->owner->type;
 
-	/* We're going to replace the current step-resume breakpoint
-	   with a longjmp-resume breakpoint.  */
-	delete_step_resume_breakpoint (ecs->event_thread);
-
-	/* Insert a breakpoint at resume address.  */
-	insert_longjmp_resume_breakpoint (gdbarch, jmp_buf_pc);
-
-	keep_going (ecs);
-	return;
-
-      case BPSTAT_WHAT_CLEAR_LONGJMP_RESUME:
         if (debug_infrun)
-	  fprintf_unfiltered (gdb_stdlog,
-			      "infrun: BPSTAT_WHAT_CLEAR_LONGJMP_RESUME\n");
-
-	gdb_assert (ecs->event_thread->step_resume_breakpoint != NULL);
-	delete_step_resume_breakpoint (ecs->event_thread);
-
-	ecs->event_thread->stop_step = 1;
-	print_stop_reason (END_STEPPING_RANGE, 0);
-	stop_stepping (ecs);
-	return;
+	  fprintf_unfiltered (gdb_stdlog, "infrun: %s\n",
+			      breakpoint_type_name (bptype));
 
-      case BPSTAT_WHAT_SINGLE:
-        if (debug_infrun)
-	  fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_SINGLE\n");
-	ecs->event_thread->stepping_over_breakpoint = 1;
-	/* Still need to check other stuff, at least the case
-	   where we are stepping and step out of the right range.  */
-	break;
+	switch (bptype)
+	  {
+	  case bp_none:
+	    perform = pe_check_more;
+	    break;
+	  case bp_breakpoint:
+	  case bp_hardware_breakpoint:
+	  case bp_until:
+	  case bp_finish:
+	    if (bs->stop)
+	      {
+		print_frame = bs->print ? pf_yes : pf_no;
+		perform = pe_stop;
+	      }
+	    else
+	      {
+		ecs->event_thread->stepping_over_breakpoint = 1;
+		perform = pe_check_more;
+	      }
+	    break;
+	  case bp_watchpoint:
+	  case bp_hardware_watchpoint:
+	  case bp_read_watchpoint:
+	  case bp_access_watchpoint:
+	  case bp_catchpoint:
+	    if (bs->stop)
+	      {
+		print_frame = bs->print ? pf_yes : pf_no;
+		perform = pe_stop;
+	      }
+	    else
+	      {
+		/* There was a watchpoint or catchpoint, but we're not
+		   stopping.  This requires no further action.  */
+		perform = pe_check_more;
+	      }
+	    break;
+	  case bp_longjmp:
+	    {
+	      struct frame_info *frame = get_current_frame ();
+	      struct gdbarch *gdbarch = get_frame_arch (frame);
 
-      case BPSTAT_WHAT_STOP_NOISY:
-        if (debug_infrun)
-	  fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_STOP_NOISY\n");
-	stop_print_frame = 1;
+	      /* If we hit the breakpoint at longjmp while stepping, we
+		 install a momentary breakpoint at the target of the
+		 jmp_buf.  */
 
-	/* We are about to nuke the step_resume_breakpointt via the
-	   cleanup chain, so no need to worry about it here.  */
+	      CORE_ADDR jmp_buf_pc;
+	      if (gdbarch_get_longjmp_target_p (gdbarch)
+		  && gdbarch_get_longjmp_target (gdbarch, frame, &jmp_buf_pc))
+		{
+		  /* We're going to replace the current step-resume breakpoint
+		     with a longjmp-resume breakpoint.  */
+		  delete_step_resume_breakpoint (ecs->event_thread);
 
-	stop_stepping (ecs);
-	return;
+		  /* Insert a breakpoint at resume address.  */
+		  insert_longjmp_resume_breakpoint (gdbarch, jmp_buf_pc);
+		}
 
-      case BPSTAT_WHAT_STOP_SILENT:
-        if (debug_infrun)
-	  fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_STOP_SILENT\n");
-	stop_print_frame = 0;
+	      ecs->event_thread->stepping_over_breakpoint = 1;
+	      perform = pe_going;
+	    }
+	    break;
+	  case bp_longjmp_resume:
+	    gdb_assert (ecs->event_thread->step_resume_breakpoint != NULL);
+	    delete_step_resume_breakpoint (ecs->event_thread);
+	    stop_step = ss_print_no;
+	    perform = pe_stop_end_range;
+	    break;
+	  case bp_step_resume:
+	    if (bs->stop)
+	      {
+		delete_step_resume_breakpoint (ecs->event_thread);
+		if (ecs->event_thread->step_after_step_resume_breakpoint)
+		  {
+		    /* Back when the step-resume breakpoint was inserted, we
+		       were trying to single-step off a breakpoint.  Go back
+		       to doing that.  pe_going must override pe_check_more so
+		       that we do not stop again on that breakpoint.  */
+		    ecs->event_thread->step_after_step_resume_breakpoint = 0;
+		    ecs->event_thread->stepping_over_breakpoint = 1;
+		    perform = pe_going;
+		  }
+		else if (stop_pc == ecs->stop_func_start
+			 && execution_direction == EXEC_REVERSE)
+		  {
+		    /* We are stepping over a function call in reverse, and
+		       just hit the step-resume breakpoint at the start
+		       address of the function.  Go back to single-stepping,
+		       which should take us back to the function call.  */
+		    ecs->event_thread->stepping_over_breakpoint = 1;
+		    perform = pe_going;
+		  }
+		else
+		  perform = pe_check_more;
+	      }
+	    else
+	      {
+		/* It is for the wrong frame.  */
+		ecs->event_thread->stepping_over_breakpoint = 1;
+		perform = pe_check_more;
+	      }
+	    break;
+	  case bp_watchpoint_scope:
+	  case bp_thread_event:
+	  case bp_overlay_event:
+	  case bp_longjmp_master:
+	  case bp_std_terminate_master:
+	    ecs->event_thread->stepping_over_breakpoint = 1;
+	    perform = pe_check_more;
+	    break;
+	  case bp_shlib_event:
+	    perform_shlib = 1;
+
+	    /* If requested, stop when the dynamic linker notifies
+	       gdb of events.  This allows the user to get control
+	       and place breakpoints in initializer routines for
+	       dynamically loaded objects (among other things).  */
+	    if (stop_on_solib_events || stop_stack_dummy)
+	      perform = pe_stop;
+	    else
+	      {
+		/* We want to step over this breakpoint, then keep going.  */
+		ecs->event_thread->stepping_over_breakpoint = 1;
+		perform = pe_check_more;
+	      }
+	    break;
+	  case bp_jit_event:
+	    /* Switch terminal for any messages produced by breakpoint_re_set.  */
+	    target_terminal_ours_for_output ();
 
-	/* We are about to nuke the step_resume_breakpoin via the
-	   cleanup chain, so no need to worry about it here.  */
+	    {
+	      struct frame_info *frame = get_current_frame ();
+	      struct gdbarch *gdbarch = get_frame_arch (frame);
 
-	stop_stepping (ecs);
-	return;
+	      jit_event_handler (gdbarch);
+	    }
 
-      case BPSTAT_WHAT_STEP_RESUME:
-        if (debug_infrun)
-	  fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_STEP_RESUME\n");
+	    target_terminal_inferior ();
 
-	delete_step_resume_breakpoint (ecs->event_thread);
-	if (ecs->event_thread->step_after_step_resume_breakpoint)
-	  {
-	    /* Back when the step-resume breakpoint was inserted, we
-	       were trying to single-step off a breakpoint.  Go back
-	       to doing that.  */
-	    ecs->event_thread->step_after_step_resume_breakpoint = 0;
+	    /* We want to step over this breakpoint, then keep going.  */
 	    ecs->event_thread->stepping_over_breakpoint = 1;
-	    keep_going (ecs);
-	    return;
-	  }
-	if (stop_pc == ecs->stop_func_start
-	    && execution_direction == EXEC_REVERSE)
-	  {
-	    /* We are stepping over a function call in reverse, and
-	       just hit the step-resume breakpoint at the start
-	       address of the function.  Go back to single-stepping,
-	       which should take us back to the function call.  */
-	    ecs->event_thread->stepping_over_breakpoint = 1;
-	    keep_going (ecs);
-	    return;
+	    perform = pe_check_more;
+	    break;
+	  case bp_call_dummy:
+	    /* Make sure the action is stop (silent or noisy),
+	       so infrun.c pops the dummy frame.  */
+	    stop_stack_dummy = STOP_STACK_DUMMY;
+	    print_frame = pf_no;
+	    perform = pe_stop;
+	    break;
+	  case bp_std_terminate:
+	    /* Make sure the action is stop (silent or noisy),
+	       so infrun.c pops the dummy frame.  */
+	    stop_stack_dummy = STOP_STD_TERMINATE;
+	    print_frame = pf_no;
+	    perform = pe_stop;
+	    break;
+	  case bp_tracepoint:
+	  case bp_fast_tracepoint:
+	    /* Tracepoint hits should not be reported back to GDB, and
+	       if one got through somehow, it should have been filtered
+	       out already.  */
+	    internal_error (__FILE__, __LINE__,
+			    _("handle_inferior_event: tracepoint encountered"));
+	    break;
+	  default:
+	    internal_error (__FILE__, __LINE__,
+			    _("handle_inferior_event: Unhandled bptype %s"),
+			    breakpoint_type_name (bptype));
+	    break;
 	  }
-	break;
 
-      case BPSTAT_WHAT_CHECK_SHLIBS:
-	{
-          if (debug_infrun)
-	    fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_CHECK_SHLIBS\n");
+	/* PERFORM must be always decided.  */
+	if (perform == pe_undef)
+	  internal_error (__FILE__, __LINE__,
+			  _("handle_inferior_event: Unset perform, bptype %s"),
+			  breakpoint_type_name (bptype));
 
-	  /* Check for any newly added shared libraries if we're
-	     supposed to be adding them automatically.  Switch
-	     terminal for any messages produced by
-	     breakpoint_re_set.  */
-	  target_terminal_ours_for_output ();
-	  /* NOTE: cagney/2003-11-25: Make certain that the target
-	     stack's section table is kept up-to-date.  Architectures,
-	     (e.g., PPC64), use the section table to perform
-	     operations such as address => section name and hence
-	     require the table to contain all sections (including
-	     those found in shared libraries).  */
+	if (debug_infrun)
+	  {
+	    const char *bptype_s = breakpoint_type_name (bptype);
+
+	    if (print_frame != pf_default)
+	      fprintf_unfiltered (gdb_stdlog, "infrun: %s: print_frame %s\n",
+				  bptype_s, print_frame == pf_no ? "pf_no"
+								 : "pf_yes");
+	    if (stop_step != ss_default)
+	      fprintf_unfiltered (gdb_stdlog, "infrun: %s: stop_step %s\n",
+				  bptype_s, stop_step_max == ss_print_no
+					    ? "ss_print_no (stop_step 1)"
+					    : "ss_print_yes (stop_step 0)");
+	    fprintf_unfiltered (gdb_stdlog, "infrun: %s: perform %s\n",
+				bptype_s,
+				perform == pe_going
+				  ? "pe_going"
+				  : perform == pe_check_more
+				    ? "pe_check_more"
+				    : perform == pe_stop
+				      ? "pe_stop" : "pe_stop_end_range");
+	  }
+	
+	if (print_frame_max < print_frame)
+	  print_frame_max = print_frame;
+	if (stop_step_max < stop_step)
+	  stop_step_max = stop_step;
+	if (perform_max < perform)
+	  perform_max = perform;
+      }
+    if (debug_infrun)
+      fprintf_unfiltered (gdb_stdlog,
+			  _("infrun: summary: print_frame %s\n"
+			    "infrun: summary: stop_step %s\n"
+			    "infrun: summary: perform %s\n"),
+			  print_frame_max == pf_default
+			    ? "pf_default (pf_yes)"
+			    : print_frame_max == pf_no ? "pf_no" : "pf_yes",
+			  stop_step_max == ss_default
+			    ? "ss_default (ss_print_yes (stop_step 0))"
+			    : stop_step_max == ss_print_no
+			      ? "ss_print_no (stop_step 1)"
+			      : "ss_print_yes (stop_step 0)",
+			  perform_max == pe_check_more
+			    ? "pe_check_more"
+			    : perform_max == pe_stop
+			      ? "pe_stop" : perform_max == pe_stop_end_range
+					    ? "pe_stop_end_range" : "pe_going");
+    if (print_frame_max == pf_default)
+      print_frame_max = pf_yes;
+    if (stop_step_max == ss_default)
+      stop_step_max = ss_print_yes;
+    gdb_assert (perform_max != pe_undef);
+
+    if (perform_shlib)
+      {
+	/* Check for any newly added shared libraries if we're
+	   supposed to be adding them automatically.  Switch
+	   terminal for any messages produced by
+	   breakpoint_re_set.  */
+	target_terminal_ours_for_output ();
+	/* NOTE: cagney/2003-11-25: Make certain that the target
+	   stack's section table is kept up-to-date.  Architectures,
+	   (e.g., PPC64), use the section table to perform
+	   operations such as address => section name and hence
+	   require the table to contain all sections (including
+	   those found in shared libraries).  */
 #ifdef SOLIB_ADD
-	  SOLIB_ADD (NULL, 0, &current_target, auto_solib_add);
+	SOLIB_ADD (NULL, 0, &current_target, auto_solib_add);
 #else
-	  solib_add (NULL, 0, &current_target, auto_solib_add);
+	solib_add (NULL, 0, &current_target, auto_solib_add);
 #endif
-	  target_terminal_inferior ();
-
-	  /* If requested, stop when the dynamic linker notifies
-	     gdb of events.  This allows the user to get control
-	     and place breakpoints in initializer routines for
-	     dynamically loaded objects (among other things).  */
-	  if (stop_on_solib_events || stop_stack_dummy)
-	    {
-	      stop_stepping (ecs);
-	      return;
-	    }
-	  else
-	    {
-	      /* We want to step over this breakpoint, then keep going.  */
-	      ecs->event_thread->stepping_over_breakpoint = 1;
-	      break;
-	    }
-	}
-	break;
-
-      case BPSTAT_WHAT_CHECK_JIT:
-        if (debug_infrun)
-          fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_CHECK_JIT\n");
-
-        /* Switch terminal for any messages produced by breakpoint_re_set.  */
-        target_terminal_ours_for_output ();
-
-        jit_event_handler (gdbarch);
-
-        target_terminal_inferior ();
-
-        /* We want to step over this breakpoint, then keep going.  */
-        ecs->event_thread->stepping_over_breakpoint = 1;
-
-        break;
-
-      case BPSTAT_WHAT_LAST:
-	/* Not a real code, but listed here to shut up gcc -Wall.  */
+	target_terminal_inferior ();
+      }
 
-      case BPSTAT_WHAT_KEEP_CHECKING:
+    stop_print_frame = print_frame_max == pf_yes;
+    ecs->event_thread->stop_step = stop_step_max == ss_print_no;
+    switch (perform_max)
+    {
+      case pe_check_more:
+	/* Still need to check other stuff, at least the case
+	   where we are stepping and step out of the right range.  */
 	break;
-      }
+      case pe_stop_end_range:
+	print_stop_reason (END_STEPPING_RANGE, 0);
+	/* FALLTHRU */
+      case pe_stop:
+	/* We are about to nuke the step_resume_breakpointt via the
+	   cleanup chain, so no need to worry about it here.  */
+	stop_stepping (ecs);
+	return;
+      case pe_going:
+	keep_going (ecs);
+	return;
+    }
   }
 
   /* We come here if we hit a breakpoint but should not
@@ -4258,6 +4430,7 @@ infrun: not switching back to stepped thread, it has vanished\n");
      the frame cache to be re-initialized, making our FRAME variable
      a dangling pointer.  */
   frame = get_current_frame ();
+  gdbarch = get_frame_arch (frame);
 
   /* If stepping through a line, keep going if still within it.
 
--- /dev/null
+++ b/gdb/testsuite/gdb.base/break-solib-event.exp
@@ -0,0 +1,90 @@
+# Copyright 2010 Free Software Foundation, Inc.
+
+# 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 3 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, see <http://www.gnu.org/licenses/>.
+
+if {[skip_shlib_tests]} {
+    return 0
+}
+
+set testfile "break-solib-event"
+set libfile "unloadshr"
+set libfile2 "unloadshr2"
+set libname "${testfile}-{libfile}.sl"
+set libname2 "${testfile}-{libfile2}.sl"
+set libsrcfile ${libfile}.c
+set libsrcfile2 ${libfile2}.c
+set srcfile $srcdir/$subdir/unload.c
+set executable $testfile
+set binfile $objdir/$subdir/$executable
+set shlibdir ${objdir}/${subdir}
+set libsrc  $srcdir/$subdir/$libfile.c
+set libsrc2  $srcdir/$subdir/$libfile2.c
+set lib_sl  $objdir/$subdir/$libname
+set lib_sl2  $objdir/$subdir/$libname2
+set lib_dlopen [shlib_target_file ${libname}]
+set lib_dlopen2 [shlib_target_file ${libname2}]
+set lib_syms [shlib_symbol_file ${libname}]
+set lib_syms2 [shlib_symbol_file ${libname2}]
+
+if [get_compiler_info ${binfile}] {
+    return -1
+}
+
+set lib_opts debug
+set exec_opts [list debug shlib_load additional_flags=-DSHLIB_NAME\=\"${lib_dlopen}\" additional_flags=-DSHLIB_NAME2\=\"${lib_dlopen2}\"]
+
+if { [gdb_compile_shlib $libsrc $lib_sl $lib_opts] != ""
+     || [gdb_compile_shlib $libsrc2 $lib_sl2 $lib_opts] != ""
+     || [gdb_compile $srcfile $binfile executable $exec_opts] != ""} {
+    untested "Couldn't compile $libsrc or $libsrc2 or $srcfile."
+    return -1
+}
+
+clean_restart $executable
+gdb_load_shlibs $lib_sl $lib_sl2
+
+gdb_test "set stop-on-solib-events 1"
+
+set event_msg "Stopped due to shared library event"
+
+gdb_run_cmd
+gdb_test "" "${event_msg}.*" "stop at event"
+
+# gdb_breakpoint {*$pc} or {*$} creates a "floating" breakpoint - changing its
+# position on breakpoint_re_set (which happens on bp_shlib_event).
+set test {p/x $pc}
+set event ""
+gdb_test_multiple $test $test {
+    -re " = (0x\[0-9a-f\]+)\r\n$gdb_prompt $" {
+       set event $expect_out(1,string)
+       pass $test
+    }
+}      
+gdb_breakpoint "*$event"
+
+set test {commands $bpnum}
+gdb_test_multiple $test $test {
+    -re "\r\n>$" {
+	pass $test
+    }
+}
+set test {echo event-hit\n}
+gdb_test_multiple $test $test {
+    -re "\r\n>$" {
+	pass $test
+    }
+}
+gdb_test "end"
+
+gdb_test "continue" "${event_msg}.*event-hit.*"


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]