Thu Aug 7 13:39:31 1997 Geoffrey Noer <noer@cygnus.com>
[deliverable/binutils-gdb.git] / gdb / breakpoint.c
index aebc62ae04d54a945f07f9337c250e7622e5a615..e1355c962013eea0c777ebf164e5d2a5549397c5 100644 (file)
@@ -1,5 +1,5 @@
 /* Everything about breakpoints, for GDB.
-   Copyright 1986, 1987, 1989, 1990, 1991, 1992, 1993, 1994, 1995
+   Copyright 1986, 1987, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
              Free Software Foundation, Inc.
 
 This file is part of GDB.
@@ -30,7 +30,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include "value.h"
 #include "command.h"
 #include "inferior.h"
-#include "thread.h"
+#include "gdbthread.h"
 #include "target.h"
 #include "language.h"
 #include "gdb_string.h"
@@ -118,7 +118,7 @@ static int
 breakpoint_cond_eval PARAMS ((char *));
 
 static void
-cleanup_executing_breakpoints PARAMS ((int));
+cleanup_executing_breakpoints PARAMS ((PTR));
 
 static void
 commands_command PARAMS ((char *, int));
@@ -135,6 +135,50 @@ set_breakpoint_count PARAMS ((int));
 static int
 remove_breakpoint PARAMS ((struct breakpoint *));
 
+static int
+print_it_normal PARAMS ((bpstat));
+
+static int
+watchpoint_check PARAMS ((char *));
+
+static int
+print_it_done PARAMS ((bpstat));
+
+static int
+print_it_noop PARAMS ((bpstat));
+
+static void
+maintenance_info_breakpoints PARAMS ((char *, int));
+
+#ifdef GET_LONGJMP_TARGET
+static void
+create_longjmp_breakpoint PARAMS ((char *));
+#endif
+
+static int
+hw_breakpoint_used_count PARAMS ((void));
+
+static int
+hw_watchpoint_used_count PARAMS ((enum bptype, int *));
+
+static void
+hbreak_command PARAMS ((char *, int));
+
+static void
+thbreak_command PARAMS ((char *, int));
+
+static void
+watch_command_1 PARAMS ((char *, int, int));
+
+static void
+rwatch_command PARAMS ((char *, int));
+
+static void
+awatch_command PARAMS ((char *, int));
+
+static void
+do_enable_breakpoint PARAMS ((struct breakpoint *, enum bpdisp));
+
 extern int addressprint;               /* Print machine addresses? */
 
 /* Are we executing breakpoint commands?  */
@@ -330,10 +374,9 @@ commands_command (arg, from_tty)
   ALL_BREAKPOINTS (b)
     if (b->number == bnum)
       {
-       if (from_tty && input_from_terminal_p ())
-         printf_filtered ("Type commands for when breakpoint %d is hit, one per line.\n\
-End with a line saying just \"end\".\n", bnum);
-       l = read_command_lines ();
+       char tmpbuf[128];
+       sprintf (tmpbuf, "Type commands for when breakpoint %d is hit, one per line.", bnum);
+       l = read_command_lines (tmpbuf, from_tty);
        free_command_lines (&b->commands);
        b->commands = l;
        breakpoints_changed ();
@@ -447,16 +490,17 @@ read_memory_nobpt (memaddr, myaddr, len)
 int
 insert_breakpoints ()
 {
-  register struct breakpoint *b;
+  register struct breakpoint *b, *temp;
   int val = 0;
   int disabled_breaks = 0;
 
-  ALL_BREAKPOINTS (b)
+  ALL_BREAKPOINTS_SAFE (b, temp)
     if (b->type != bp_watchpoint
        && b->type != bp_hardware_watchpoint
        && b->type != bp_read_watchpoint
        && b->type != bp_access_watchpoint
        && b->enable != disabled
+       && b->enable != shlib_disabled
        && ! b->inserted
        && ! b->duplicate)
       {
@@ -471,13 +515,13 @@ insert_breakpoints ()
            if (DISABLE_UNSETTABLE_BREAK (b->address))
              {
                val = 0;
-               b->enable = disabled;
+               b->enable = shlib_disabled;
                if (!disabled_breaks)
                  {
                    target_terminal_ours_for_output ();
                    fprintf_unfiltered (gdb_stderr,
                         "Cannot insert breakpoint %d:\n", b->number);
-                   printf_filtered ("Disabling shared library breakpoints:\n");
+                   printf_filtered ("Temporarily disabling shared library breakpoints:\n");
                  }
                disabled_breaks = 1;
                printf_filtered ("%d ", b->number);
@@ -573,8 +617,12 @@ insert_breakpoints ()
 Hardware watchpoint %d deleted because the program has left the block in\n\
 which its expression is valid.\n", b->number);
            if (b->related_breakpoint)
-             delete_breakpoint (b->related_breakpoint);
-           delete_breakpoint (b);
+             {
+               b->related_breakpoint->enable = disable;
+               b->related_breakpoint->disposition = del_at_next_stop;
+             }
+           b->enable = disable;
+           b->disposition = del_at_next_stop;
          }
 
        /* Restore the frame and level.  */
@@ -652,8 +700,8 @@ remove_breakpoint (b)
        }
       /* Failure to remove any of the hardware watchpoints comes here.  */
       if (b->inserted)
-       error ("Hardware watchpoint %d: Could not remove watchpoint\n",
-              b->number);
+       warning ("Hardware watchpoint %d: Could not remove watchpoint\n",
+                b->number);
       
       /* Free the saved value chain.  We will construct a new one
         the next time the watchpoint is inserted.  */
@@ -690,21 +738,32 @@ breakpoint_init_inferior ()
     {
       b->inserted = 0;
 
-      /* If the call dummy breakpoint is at the entry point it will
-        cause problems when the inferior is rerun, so we better
-        get rid of it.  */
-      if (b->type == bp_call_dummy)
-       delete_breakpoint (b);
+      switch (b->type)
+       {
+       case bp_call_dummy:
+       case bp_watchpoint_scope:
 
-      /* Likewise for scope breakpoints.  */
-      if (b->type == bp_watchpoint_scope)
-       delete_breakpoint (b);
+         /* If the call dummy breakpoint is at the entry point it will
+            cause problems when the inferior is rerun, so we better
+            get rid of it. 
 
-      /* Likewise for watchpoints on local expressions.  */
-      if ((b->type == bp_watchpoint || b->type == bp_hardware_watchpoint ||
-           b->type == bp_read_watchpoint || b->type == bp_access_watchpoint)
-         && b->exp_valid_block != NULL)
-       delete_breakpoint (b);
+            Also get rid of scope breakpoints.  */
+         delete_breakpoint (b);
+         break;
+
+       case bp_watchpoint:
+       case bp_hardware_watchpoint:
+       case bp_read_watchpoint:
+       case bp_access_watchpoint:
+
+         /* Likewise for watchpoints on local expressions.  */
+         if (b->exp_valid_block != NULL)
+           delete_breakpoint (b);
+         break;
+
+       default:
+         break;
+       }
     }
 }
 
@@ -719,7 +778,9 @@ breakpoint_here_p (pc)
   register struct breakpoint *b;
 
   ALL_BREAKPOINTS (b)
-    if (b->enable != disabled && b->address == pc)
+    if (b->enable != disabled
+       && b->enable != shlib_disabled
+       && b->address == pc)
       return 1;
 
   return 0;
@@ -771,6 +832,7 @@ breakpoint_thread_match (pc, pid)
 
   ALL_BREAKPOINTS (b)
     if (b->enable != disabled
+       && b->enable != shlib_disabled
        && b->address == pc
        && (b->thread == -1 || b->thread == thread))
       return 1;
@@ -896,7 +958,7 @@ bpstat_clear_actions (bs)
 /* ARGSUSED */
 static void
 cleanup_executing_breakpoints (ignore)
-     int ignore;
+     PTR ignore;
 {
   executing_breakpoint_commands = 0;
 }
@@ -914,6 +976,11 @@ bpstat_do_actions (bsp)
   struct cleanup *old_chain;
   struct command_line *cmd;
 
+  /* Avoid endless recursion if a `source' command is contained
+     in bs->commands.  */
+  if (executing_breakpoint_commands)
+    return;
+
   executing_breakpoint_commands = 1;
   old_chain = make_cleanup (cleanup_executing_breakpoints, 0);
 
@@ -1147,8 +1214,12 @@ watchpoint_check (p)
 Watchpoint %d deleted because the program has left the block in\n\
 which its expression is valid.\n", bs->breakpoint_at->number);
       if (b->related_breakpoint)
-       delete_breakpoint (b->related_breakpoint);
-      delete_breakpoint (b);
+       {
+         b->related_breakpoint->enable = disable;
+         b->related_breakpoint->disposition = del_at_next_stop;
+       }
+      b->enable = disable;
+      b->disposition = del_at_next_stop;
 
       return WP_DELETED;
     }
@@ -1199,7 +1270,7 @@ bpstat_stop_status (pc, not_a_breakpoint)
      CORE_ADDR *pc;
      int not_a_breakpoint;
 {
-  register struct breakpoint *b;
+  register struct breakpoint *b, *temp;
   CORE_ADDR bp_addr;
 #if DECR_PC_AFTER_BREAK != 0 || defined (SHIFT_INST_REGS)
   /* True if we've hit a breakpoint (as opposed to a watchpoint).  */
@@ -1216,9 +1287,10 @@ bpstat_stop_status (pc, not_a_breakpoint)
   /* Get the address where the breakpoint would have been.  */
   bp_addr = *pc - DECR_PC_AFTER_BREAK;
 
-  ALL_BREAKPOINTS (b)
+  ALL_BREAKPOINTS_SAFE (b, temp)
     {
-      if (b->enable == disabled)
+      if (b->enable == disabled
+         || b->enable == shlib_disabled)
        continue;
 
       if (b->type != bp_watchpoint
@@ -1275,8 +1347,12 @@ bpstat_stop_status (pc, not_a_breakpoint)
              /* Error from catch_errors.  */
              printf_filtered ("Watchpoint %d deleted.\n", b->number);
              if (b->related_breakpoint)
-               delete_breakpoint (b->related_breakpoint);
-             delete_breakpoint (b);
+               {
+                 b->related_breakpoint->enable = disable;
+                 b->related_breakpoint->disposition = del_at_next_stop;
+               }
+             b->enable = disable;
+             b->disposition = del_at_next_stop;
              /* We've already printed what needs to be printed.  */
              bs->print_it = print_it_done;
 
@@ -1321,9 +1397,13 @@ bpstat_stop_status (pc, not_a_breakpoint)
                 case 0:
                   /* Error from catch_errors.  */
                   printf_filtered ("Watchpoint %d deleted.\n", b->number);
-                  if (b->related_breakpoint)
-                    delete_breakpoint (b->related_breakpoint);
-                  delete_breakpoint (b);
+                 if (b->related_breakpoint)
+                   {
+                     b->related_breakpoint->enable = disable;
+                     b->related_breakpoint->disposition = del_at_next_stop;
+                   }
+                 b->enable = disable;
+                 b->disposition = del_at_next_stop;
                   /* We've already printed what needs to be printed.  */
                   bs->print_it = print_it_done;
                   break;
@@ -1448,6 +1528,9 @@ bpstat_what (bs)
     /* We hit the through_sigtramp breakpoint.  */
     through_sig,
 
+    /* We hit the shared library event breakpoint.  */
+    shlib_event,
+
     /* This is just used to count how many enums there are.  */
     class_last
     };
@@ -1455,15 +1538,16 @@ bpstat_what (bs)
   /* 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 keep_c BPSTAT_WHAT_KEEP_CHECKING
-#define stop_s BPSTAT_WHAT_STOP_SILENT
-#define stop_n BPSTAT_WHAT_STOP_NOISY
-#define single BPSTAT_WHAT_SINGLE
-#define setlr BPSTAT_WHAT_SET_LONGJMP_RESUME
-#define clrlr BPSTAT_WHAT_CLEAR_LONGJMP_RESUME
-#define clrlrs BPSTAT_WHAT_CLEAR_LONGJMP_RESUME_SINGLE
+#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 clrs BPSTAT_WHAT_CLEAR_LONGJMP_RESUME_SINGLE
 #define sr BPSTAT_WHAT_STEP_RESUME
 #define ts BPSTAT_WHAT_THROUGH_SIGTRAMP
+#define shl BPSTAT_WHAT_CHECK_SHLIBS
 
 /* "Can't happen."  Might want to print an error message.
    abort() is not out of the question, but chances are GDB is just
@@ -1488,29 +1572,31 @@ bpstat_what (bs)
     table[(int)class_last][(int)BPSTAT_WHAT_LAST] =
       {
        /*                              old action */
-       /*       keep_c stop_s stop_n single  setlr   clrlr   clrlrs  sr  ts
+       /*       kc   ss   sn   sgl   slr  clr   clrs  sr   ts  shl
         */
-/*no_effect*/  {keep_c,stop_s,stop_n,single, setlr , clrlr , clrlrs, sr, ts},
-/*wp_silent*/  {stop_s,stop_s,stop_n,stop_s, stop_s, stop_s, stop_s, sr, ts},
-/*wp_noisy*/    {stop_n,stop_n,stop_n,stop_n, stop_n, stop_n, stop_n, sr, ts},
-/*bp_nostop*/  {single,stop_s,stop_n,single, setlr , clrlrs, clrlrs, sr, ts},
-/*bp_silent*/  {stop_s,stop_s,stop_n,stop_s, stop_s, stop_s, stop_s, sr, ts},
-/*bp_noisy*/    {stop_n,stop_n,stop_n,stop_n, stop_n, stop_n, stop_n, sr, ts},
-/*long_jump*/  {setlr ,stop_s,stop_n,setlr , err   , err   , err   , sr, ts},
-/*long_resume*/        {clrlr ,stop_s,stop_n,clrlrs, err   , err   , err   , sr, ts},
-/*step_resume*/        {sr    ,sr    ,sr    ,sr    , sr    , sr    , sr    , sr, ts},
-/*through_sig*/ {ts    ,ts    ,ts    ,ts    , ts    , ts    , ts    , ts, ts}
+/*no_effect*/  {kc,  ss,  sn,  sgl,  slr, clr,  clrs, sr,  ts, shl},
+/*wp_silent*/  {ss,  ss,  sn,  ss,   ss,  ss,   ss,   sr,  ts, shl},
+/*wp_noisy*/    {sn,  sn,  sn,  sn,   sn,  sn,   sn,   sr,  ts, shl},
+/*bp_nostop*/  {sgl, ss,  sn,  sgl,  slr, clrs, clrs, sr,  ts, shl},
+/*bp_silent*/  {ss,  ss,  sn,  ss,   ss,  ss,   ss,   sr,  ts, shl},
+/*bp_noisy*/    {sn,  sn,  sn,  sn,   sn,  sn,   sn,   sr,  ts, shl},
+/*long_jump*/  {slr, ss,  sn,  slr,  err, err,  err,  sr,  ts, shl},
+/*long_resume*/        {clr, ss,  sn,  clrs, err, err,  err,  sr,  ts, shl},
+/*step_resume*/        {sr,  sr,  sr,  sr,   sr,  sr,   sr,   sr,  ts, shl},
+/*through_sig*/ {ts,  ts,  ts,  ts,   ts,  ts,   ts,   ts,  ts, shl},
+/*shlib*/       {shl, shl, shl, shl,  shl, shl,  shl,  shl, ts, shl}
              };
-#undef keep_c
-#undef stop_s
-#undef stop_n
-#undef single
-#undef setlr
-#undef clrlr
-#undef clrlrs
+#undef kc
+#undef ss
+#undef sn
+#undef sgl
+#undef slr
+#undef clr
+#undef clrs
 #undef err
 #undef sr
 #undef ts
+#undef shl
   enum bpstat_what_main_action current_action = BPSTAT_WHAT_KEEP_CHECKING;
   struct bpstat_what retval;
 
@@ -1575,7 +1661,9 @@ bpstat_what (bs)
        case bp_watchpoint_scope:
          bs_class = bp_nostop;
          break;
-
+       case bp_shlib_event:
+         bs_class = shlib_event;
+         break;
        case bp_call_dummy:
          /* Make sure the action is stop (silent or noisy), so infrun.c
             pops the dummy frame.  */
@@ -1622,9 +1710,11 @@ breakpoint_1 (bnum, allflag)
                              "hw watchpoint", "read watchpoint",
                              "acc watchpoint", "longjmp",
                              "longjmp resume", "step resume",
-                             "watchpoint scope", "call dummy" };
-  static char *bpdisps[] = {"del", "dis", "keep"};
-  static char bpenables[] = "ny";
+                             "sigtramp",
+                             "watchpoint scope", "call dummy",
+                             "shlib events" };
+  static char *bpdisps[] = {"del", "dstp", "dis", "keep"};
+  static char bpenables[] = "nyn";
   char wrap_indent[80];
 
   ALL_BREAKPOINTS (b)
@@ -1700,6 +1790,7 @@ breakpoint_1 (bnum, allflag)
          case bp_through_sigtramp:
          case bp_watchpoint_scope:
          case bp_call_dummy:
+         case bp_shlib_event:
            if (addressprint)
              {
                annotate_field (4);
@@ -1752,6 +1843,12 @@ breakpoint_1 (bnum, allflag)
            printf_filtered ("\n");
          }
 
+       if (b->thread != -1)
+         {
+           /* FIXME should make an annotation for this */
+           printf_filtered ("\tstop only in thread %d\n", b->thread);
+         }
+
         if (show_breakpoint_hit_counts && b->hit_count)
          {
            /* FIXME should make an annotation for this */
@@ -1849,7 +1946,8 @@ describe_other_breakpoints (pc)
            printf_filtered
              ("%d%s%s ",
               b->number,
-              (b->enable == disabled) ? " (disabled)" : "",
+              ((b->enable == disabled || b->enable == shlib_disabled)
+               ? " (disabled)" : ""),
               (others > 1) ? "," : ((others == 1) ? " and" : ""));
          }
       printf_filtered ("also set at pc ");
@@ -1889,7 +1987,9 @@ check_duplicates (address)
     return;
 
   ALL_BREAKPOINTS (b)
-    if (b->enable != disabled && b->address == address)
+    if (b->enable != disabled
+       && b->enable != shlib_disabled
+       && b->address == address)
       {
        count++;
        b->duplicate = count > 1;
@@ -1951,13 +2051,16 @@ set_raw_breakpoint (sal)
   return b;
 }
 
+static int internal_breakpoint_number = -1;
+
+#ifdef GET_LONGJMP_TARGET
+
 static void
 create_longjmp_breakpoint (func_name)
      char *func_name;
 {
   struct symtab_and_line sal;
   struct breakpoint *b;
-  static int internal_breakpoint_number = -1;
 
   if (func_name != NULL)
     {
@@ -1987,6 +2090,8 @@ create_longjmp_breakpoint (func_name)
   b->number = internal_breakpoint_number--;
 }
 
+#endif /* #ifdef GET_LONGJMP_TARGET */
+
 /* Call this routine when stepping and nexting to enable a breakpoint if we do
    a longjmp().  When we hit that breakpoint, call
    set_longjmp_resume_breakpoint() to figure out where we are going. */
@@ -2018,7 +2123,54 @@ disable_longjmp_breakpoint()
       }
 }
 
-int
+#ifdef SOLIB_ADD
+void
+remove_solib_event_breakpoints ()
+{
+  register struct breakpoint *b, *temp;
+
+  ALL_BREAKPOINTS_SAFE (b, temp)
+    if (b->type == bp_shlib_event)
+      delete_breakpoint (b);
+}
+
+void
+create_solib_event_breakpoint (address)
+     CORE_ADDR address;
+{
+  struct breakpoint *b;
+  struct symtab_and_line sal;
+
+  sal.pc = address;
+  sal.symtab = NULL;
+  sal.line = 0;
+  b = set_raw_breakpoint (sal);
+  b->number = internal_breakpoint_number--;
+  b->disposition = donttouch;
+  b->type = bp_shlib_event;
+}
+
+/* Try to reenable any breakpoints in shared libraries.  */
+void
+re_enable_breakpoints_in_shlibs ()
+{
+  struct breakpoint *b;
+
+  ALL_BREAKPOINTS (b)
+    if (b->enable == shlib_disabled)
+      {
+       char buf[1];
+
+       /* Do not reenable the breakpoint if the shared library
+          is still not mapped in.  */
+       if (target_read_memory (b->address, buf, 1) == 0)
+         b->enable = enabled;
+      }
+}
+
+#endif
+
+static int
 hw_breakpoint_used_count()
 {
   register struct breakpoint *b;
@@ -2033,7 +2185,7 @@ hw_breakpoint_used_count()
   return i;
 }
 
-int
+static int
 hw_watchpoint_used_count(type, other_type_used)
     enum bptype type;
     int *other_type_used;
@@ -2111,19 +2263,6 @@ set_momentary_breakpoint (sal, frame, type)
   return b;
 }
 
-#if 0
-void
-clear_momentary_breakpoints ()
-{
-  register struct breakpoint *b;
-  ALL_BREAKPOINTS (b)
-    if (b->disposition == delete)
-      {
-       delete_breakpoint (b);
-       break;
-      }
-}
-#endif
 \f
 /* Tell the user we have just set a breakpoint B.  */
 
@@ -2175,6 +2314,7 @@ mention (b)
     case bp_through_sigtramp:
     case bp_call_dummy:
     case bp_watchpoint_scope:
+    case bp_shlib_event:
       break;
     }
   if (say_where)
@@ -2191,43 +2331,6 @@ mention (b)
   printf_filtered ("\n");
 }
 
-#if 0
-/* Nobody calls this currently. */
-/* Set a breakpoint from a symtab and line.
-   If TEMPFLAG is nonzero, it is a temporary breakpoint.
-   ADDR_STRING is a malloc'd string holding the name of where we are
-   setting the breakpoint.  This is used later to re-set it after the
-   program is relinked and symbols are reloaded.
-   Print the same confirmation messages that the breakpoint command prints.  */
-
-void
-set_breakpoint (s, line, tempflag, addr_string)
-     struct symtab *s;
-     int line;
-     int tempflag;
-     char *addr_string;
-{
-  register struct breakpoint *b;
-  struct symtab_and_line sal;
-  
-  sal.symtab = s;
-  sal.line = line;
-  sal.pc = 0;
-  resolve_sal_pc (&sal);                       /* Might error out */
-  describe_other_breakpoints (sal.pc);
-
-  b = set_raw_breakpoint (sal);
-  set_breakpoint_count (breakpoint_count + 1);
-  b->number = breakpoint_count;
-  b->type = bp_breakpoint;
-  b->cond = 0;
-  b->addr_string = addr_string;
-  b->enable = enabled;
-  b->disposition = tempflag ? delete : donttouch;
-
-  mention (b);
-}
-#endif /* 0 */
 \f
 /* Set a breakpoint according to ARG (function, linenum or *address)
    flag: first bit  : 0 non-temporary, 1 temporary.
@@ -2486,7 +2589,8 @@ watch_command_1 (arg, accessflag, from_tty)
   struct expression *exp;
   struct block *exp_valid_block;
   struct value *val, *mark;
-  struct frame_info *frame, *prev_frame;
+  struct frame_info *frame;
+  struct frame_info *prev_frame = NULL;
   char *exp_start = NULL;
   char *exp_end = NULL;
   char *tok, *end_tok;
@@ -3159,17 +3263,26 @@ clear_command (arg, from_tty)
   free ((PTR)sals.sals);
 }
 \f
-/* Delete breakpoint in BS if they are `delete' breakpoints.
+/* Delete breakpoint in BS if they are `delete' breakpoints and
+   all breakpoints that are marked for deletion, whether hit or not.
    This is called after any breakpoint is hit, or after errors.  */
 
 void
 breakpoint_auto_delete (bs)
      bpstat bs;
 {
+  struct breakpoint *b, *temp;
+
   for (; bs; bs = bs->next)
     if (bs->breakpoint_at && bs->breakpoint_at->disposition == del 
        && bs->stop)
       delete_breakpoint (bs->breakpoint_at);
+
+  ALL_BREAKPOINTS_SAFE (b, temp)
+    {
+      if (b->disposition == del_at_next_stop)
+       delete_breakpoint (b);
+    }
 }
 
 /* Delete a breakpoint and clean up all traces of it in the data structures. */
@@ -3208,7 +3321,8 @@ delete_breakpoint (bpt)
       ALL_BREAKPOINTS (b)
        if (b->address == bpt->address
            && !b->duplicate
-           && b->enable != disabled)
+           && b->enable != disabled
+           && b->enable != shlib_disabled)
          {
            int val;
            val = target_insert_breakpoint (b->address, b->shadow_contents);
@@ -3230,8 +3344,12 @@ delete_breakpoint (bpt)
     free (bpt->cond_string);
   if (bpt->addr_string != NULL)
     free (bpt->addr_string);
+  if (bpt->exp != NULL)
+    free (bpt->exp);
   if (bpt->exp_string != NULL)
     free (bpt->exp_string);
+  if (bpt->val != NULL)
+    value_free (bpt->val);
   if (bpt->source_file != NULL)
     free (bpt->source_file);
 
@@ -3364,9 +3482,13 @@ breakpoint_re_set_one (bint)
         particular level, but that's going to be less stable than filenames
         or functionnames.  */
       /* So for now, just use a global context.  */
+      if (b->exp)
+       free ((PTR)b->exp);
       b->exp = parse_expression (b->exp_string);
       b->exp_valid_block = innermost_block;
       mark = value_mark ();
+      if (b->val)
+       value_free (b->val);
       b->val = evaluate_expression (b->exp);
       release_value (b->val);
       if (VALUE_LAZY (b->val))
@@ -3375,6 +3497,8 @@ breakpoint_re_set_one (bint)
       if (b->cond_string != NULL)
        {
          s = b->cond_string;
+         if (b->cond)
+           free ((PTR)b->cond);
          b->cond = parse_exp_1 (&s, (struct block *)0, 0);
        }
       if (b->enable == enabled)
@@ -3385,13 +3509,26 @@ breakpoint_re_set_one (bint)
     default:
       printf_filtered ("Deleting unknown breakpoint type %d\n", b->type);
       /* fall through */
-    case bp_until:
-    case bp_finish:
+    /* Delete longjmp breakpoints, they will be reset later by
+       breakpoint_re_set.  */
     case bp_longjmp:
     case bp_longjmp_resume:
+      delete_breakpoint (b);
+      break;
+
+    /* This breakpoint is special, it's set up when the inferior
+       starts and we really don't want to touch it.  */
+    case bp_shlib_event:
+
+    /* Keep temporary breakpoints, which can be encountered when we step
+       over a dlopen call and SOLIB_ADD is resetting the breakpoints.
+       Otherwise these should have been blown away via the cleanup chain
+       or by breakpoint_init_inferior when we rerun the executable.  */
+    case bp_until:
+    case bp_finish:
     case bp_watchpoint_scope:
     case bp_call_dummy:
-      delete_breakpoint (b);
+    case bp_step_resume:
       break;
     }
 
@@ -3427,7 +3564,7 @@ breakpoint_re_set ()
 #endif
 
 #if 0
-  /* Took this out (temporaliy at least), since it produces an extra 
+  /* Took this out (temporarily at least), since it produces an extra 
      blank line at startup. This messes up the gdbtests. -PB */
   /* Blank line to finish off all those mention() messages we just printed.  */
   printf_filtered ("\n");
@@ -3541,113 +3678,6 @@ map_breakpoint_numbers (args, function)
     }
 }
 
-void
-enable_breakpoint (bpt)
-     struct breakpoint *bpt;
-{
-  struct frame_info *save_selected_frame = NULL;
-  int save_selected_frame_level = -1;
-  int target_resources_ok, other_type_used;
-  struct value *mark;
-  
-  if (bpt->type == bp_hardware_breakpoint)
-    {
-      int i;
-      i = hw_breakpoint_used_count();
-      target_resources_ok = TARGET_CAN_USE_HARDWARE_WATCHPOINT( 
-               bp_hardware_breakpoint, i+1, 0);
-      if (target_resources_ok == 0)
-        error ("No hardware breakpoint support in the target.");
-      else if (target_resources_ok < 0)
-        error ("Hardware breakpoints used exceeds limit.");
-    }
-  bpt->enable = enabled;
-  check_duplicates (bpt->address);
-
-  if (bpt->type == bp_watchpoint || bpt->type == bp_hardware_watchpoint ||
-      bpt->type == bp_read_watchpoint || bpt->type == bp_access_watchpoint)
-    {
-      if (bpt->exp_valid_block != NULL)
-       {
-         struct frame_info *fr =
-           find_frame_addr_in_frame_chain (bpt->watchpoint_frame);
-         if (fr == NULL)
-           {
-             printf_filtered ("\
-Cannot enable watchpoint %d because the block in which its expression\n\
-is valid is not currently in scope.\n", bpt->number);
-             bpt->enable = disabled;
-             return;
-           }
-
-         save_selected_frame = selected_frame;
-         save_selected_frame_level = selected_frame_level;
-         select_frame (fr, -1);
-       }
-
-      value_free (bpt->val);
-      mark = value_mark ();
-      bpt->val = evaluate_expression (bpt->exp);
-      release_value (bpt->val);
-      if (VALUE_LAZY (bpt->val))
-       value_fetch_lazy (bpt->val);
-
-      if (bpt->type == bp_hardware_watchpoint ||
-           bpt->type == bp_read_watchpoint ||
-           bpt->type == bp_access_watchpoint)
-      {
-        int i = hw_watchpoint_used_count (bpt->type, &other_type_used);
-        int mem_cnt = can_use_hardware_watchpoint (bpt->val);
-
-        target_resources_ok = TARGET_CAN_USE_HARDWARE_WATCHPOINT(
-                bpt->type, i + mem_cnt, other_type_used);
-        /* we can consider of type is bp_hardware_watchpoint, convert to 
-          bp_watchpoint in the following condition */
-        if (target_resources_ok < 0)
-         {
-             printf_filtered("\
-Cannot enable watchpoint %d because target watch resources\n\
-have been allocated for other watchpoints.\n", bpt->number);
-           bpt->enable = disabled;
-           value_free_to_mark (mark);
-           return;
-          }
-      }
-
-      if (save_selected_frame_level >= 0)
-       select_frame (save_selected_frame, save_selected_frame_level);
-      value_free_to_mark (mark);
-    }
-
-  if (modify_breakpoint_hook)
-    modify_breakpoint_hook (bpt);
-}
-
-/* ARGSUSED */
-static void
-enable_command (args, from_tty)
-     char *args;
-     int from_tty;
-{
-  struct breakpoint *bpt;
-  if (args == 0)
-    ALL_BREAKPOINTS (bpt)
-      switch (bpt->type)
-       {
-       case bp_breakpoint:
-       case bp_hardware_breakpoint:
-       case bp_watchpoint:
-       case bp_hardware_watchpoint:
-       case bp_read_watchpoint:
-       case bp_access_watchpoint:
-         enable_breakpoint (bpt);
-       default:
-         continue;
-       }
-  else
-    map_breakpoint_numbers (args, enable_breakpoint);
-}
-
 void
 disable_breakpoint (bpt)
      struct breakpoint *bpt;
@@ -3692,16 +3722,17 @@ disable_command (args, from_tty)
 }
 
 static void
-enable_once_breakpoint (bpt)
+do_enable_breakpoint (bpt, disposition)
      struct breakpoint *bpt;
+     enum bpdisp disposition;
 {
   struct frame_info *save_selected_frame = NULL;
   int save_selected_frame_level = -1;
   int target_resources_ok, other_type_used;
   struct value *mark;
 
-  if (bpt->type == bp_hardware_breakpoint) 
-    {   
+  if (bpt->type == bp_hardware_breakpoint)
+    {
       int i;
       i = hw_breakpoint_used_count();
       target_resources_ok = TARGET_CAN_USE_HARDWARE_WATCHPOINT(
@@ -3713,7 +3744,7 @@ enable_once_breakpoint (bpt)
     }
 
   bpt->enable = enabled;
-  bpt->disposition = disable;
+  bpt->disposition = disposition;
   check_duplicates (bpt->address);
   breakpoints_changed ();
 
@@ -3750,9 +3781,10 @@ is valid is not currently in scope.\n", bpt->number);
            bpt->type == bp_access_watchpoint)
       {
         int i = hw_watchpoint_used_count (bpt->type, &other_type_used);
-        int mem_cnt = can_use_hardware_watchpoint(bpt->val);
+        int mem_cnt = can_use_hardware_watchpoint (bpt->val);
+
         target_resources_ok = TARGET_CAN_USE_HARDWARE_WATCHPOINT(
-                bpt->type, i+mem_cnt, other_type_used);
+                bpt->type, i + mem_cnt, other_type_used);
         /* we can consider of type is bp_hardware_watchpoint, convert to 
           bp_watchpoint in the following condition */
         if (target_resources_ok < 0)
@@ -3760,8 +3792,9 @@ is valid is not currently in scope.\n", bpt->number);
              printf_filtered("\
 Cannot enable watchpoint %d because target watch resources\n\
 have been allocated for other watchpoints.\n", bpt->number);
-           bpt->enable = disabled;
-           value_free_to_mark (mark);
+            bpt->enable = disabled;
+            value_free_to_mark (mark);
+            return;
           }
       }
 
@@ -3769,6 +3802,51 @@ have been allocated for other watchpoints.\n", bpt->number);
        select_frame (save_selected_frame, save_selected_frame_level);
       value_free_to_mark (mark);
     }
+  if (modify_breakpoint_hook)
+    modify_breakpoint_hook (bpt);
+}
+
+void
+enable_breakpoint (bpt)
+     struct breakpoint *bpt;
+{
+  do_enable_breakpoint (bpt, donttouch);
+}
+
+/* The enable command enables the specified breakpoints (or all defined
+   breakpoints) so they once again become (or continue to be) effective
+   in stopping the inferior. */
+
+/* ARGSUSED */
+static void
+enable_command (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  register struct breakpoint *bpt;
+  if (args == 0)
+    ALL_BREAKPOINTS (bpt)
+      switch (bpt->type)
+       {
+       case bp_breakpoint:
+       case bp_hardware_breakpoint:
+       case bp_watchpoint:
+       case bp_hardware_watchpoint:
+       case bp_read_watchpoint:
+       case bp_access_watchpoint:
+         enable_breakpoint (bpt);
+       default:
+         continue;
+       }
+  else
+    map_breakpoint_numbers (args, enable_breakpoint);
+}
+
+static void
+enable_once_breakpoint (bpt)
+     struct breakpoint *bpt;
+{
+  do_enable_breakpoint (bpt, disable);
 }
 
 /* ARGSUSED */
@@ -3784,11 +3862,7 @@ static void
 enable_delete_breakpoint (bpt)
      struct breakpoint *bpt;
 {
-  bpt->enable = enabled;
-  bpt->disposition = del;
-
-  check_duplicates (bpt->address);
-  breakpoints_changed ();
+  do_enable_breakpoint (bpt, del);
 }
 
 /* ARGSUSED */
This page took 0.033943 seconds and 4 git commands to generate.