[gdb/breakpoints] Fix longjmp master breakpoint with separate debug info
[deliverable/binutils-gdb.git] / gdb / breakpoint.c
index 61fbc3b92b111963320fbb80f10f2d183a4dadf6..70b0d88cb45aedcf24a389e6bbfcbee0c926a8c4 100644 (file)
@@ -1,6 +1,6 @@
 /* Everything about breakpoints, for GDB.
 
-   Copyright (C) 1986-2020 Free Software Foundation, Inc.
+   Copyright (C) 1986-2021 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -172,8 +172,6 @@ static int hw_watchpoint_used_count_others (struct breakpoint *except,
 static void enable_breakpoint_disp (struct breakpoint *, enum bpdisp,
                                    int count);
 
-static void free_bp_location (struct bp_location *loc);
-static void incref_bp_location (struct bp_location *loc);
 static void decref_bp_location (struct bp_location **loc);
 
 static struct bp_location *allocate_bp_location (struct breakpoint *bpt);
@@ -2173,7 +2171,7 @@ should_be_inserted (struct bp_location *bl)
       && stepping_past_nonsteppable_watchpoint ())
     {
       infrun_debug_printf ("stepping past non-steppable watchpoint. "
-                          "skipping watchpoint at %s:%d\n",
+                          "skipping watchpoint at %s:%d",
                           paddress (bl->gdbarch, bl->address), bl->length);
       return 0;
     }
@@ -3329,100 +3327,134 @@ create_overlay_event_breakpoint (void)
     }
 }
 
-static void
-create_longjmp_master_breakpoint (void)
+/* Install a master longjmp breakpoint for OBJFILE using a probe.  Return
+   true if a breakpoint was installed.  */
+
+static bool
+create_longjmp_master_breakpoint_probe (objfile *objfile)
 {
-  scoped_restore_current_program_space restore_pspace;
+  struct gdbarch *gdbarch = objfile->arch ();
+  struct breakpoint_objfile_data *bp_objfile_data
+    = get_breakpoint_objfile_data (objfile);
 
-  for (struct program_space *pspace : program_spaces)
+  if (!bp_objfile_data->longjmp_searched)
     {
-      set_current_program_space (pspace);
+      std::vector<probe *> ret
+       = find_probes_in_objfile (objfile, "libc", "longjmp");
 
-      for (objfile *objfile : current_program_space->objfiles ())
+      if (!ret.empty ())
        {
-         int i;
-         struct gdbarch *gdbarch;
-         struct breakpoint_objfile_data *bp_objfile_data;
+         /* We are only interested in checking one element.  */
+         probe *p = ret[0];
 
-         gdbarch = objfile->arch ();
+         if (!p->can_evaluate_arguments ())
+           {
+             /* We cannot use the probe interface here,
+                because it does not know how to evaluate
+                arguments.  */
+             ret.clear ();
+           }
+       }
+      bp_objfile_data->longjmp_probes = ret;
+      bp_objfile_data->longjmp_searched = 1;
+    }
 
-         bp_objfile_data = get_breakpoint_objfile_data (objfile);
+  if (bp_objfile_data->longjmp_probes.empty ())
+    return false;
 
-         if (!bp_objfile_data->longjmp_searched)
-           {
-             std::vector<probe *> ret
-               = find_probes_in_objfile (objfile, "libc", "longjmp");
+  for (probe *p : bp_objfile_data->longjmp_probes)
+    {
+      struct breakpoint *b;
 
-             if (!ret.empty ())
-               {
-                 /* We are only interested in checking one element.  */
-                 probe *p = ret[0];
+      b = create_internal_breakpoint (gdbarch,
+                                     p->get_relocated_address (objfile),
+                                     bp_longjmp_master,
+                                     &internal_breakpoint_ops);
+      b->location = new_probe_location ("-probe-stap libc:longjmp");
+      b->enable_state = bp_disabled;
+    }
 
-                 if (!p->can_evaluate_arguments ())
-                   {
-                     /* We cannot use the probe interface here,
-                        because it does not know how to evaluate
-                        arguments.  */
-                     ret.clear ();
-                   }
-               }
-             bp_objfile_data->longjmp_probes = ret;
-             bp_objfile_data->longjmp_searched = 1;
-           }
+  return true;
+}
 
-         if (!bp_objfile_data->longjmp_probes.empty ())
-           {
-             for (probe *p : bp_objfile_data->longjmp_probes)
-               {
-                 struct breakpoint *b;
-
-                 b = create_internal_breakpoint (gdbarch,
-                                                 p->get_relocated_address (objfile),
-                                                 bp_longjmp_master,
-                                                 &internal_breakpoint_ops);
-                 b->location = new_probe_location ("-probe-stap libc:longjmp");
-                 b->enable_state = bp_disabled;
-               }
+/* Install master longjmp breakpoints for OBJFILE using longjmp_names.
+   Return true if at least one breakpoint was installed.  */
 
+static bool
+create_longjmp_master_breakpoint_names (objfile *objfile)
+{
+  struct gdbarch *gdbarch = objfile->arch ();
+  if (!gdbarch_get_longjmp_target_p (gdbarch))
+    return false;
+
+  struct breakpoint_objfile_data *bp_objfile_data
+    = get_breakpoint_objfile_data (objfile);
+  unsigned int installed_bp = 0;
+
+  for (int i = 0; i < NUM_LONGJMP_NAMES; i++)
+    {
+      struct breakpoint *b;
+      const char *func_name;
+      CORE_ADDR addr;
+      struct explicit_location explicit_loc;
+
+      if (msym_not_found_p (bp_objfile_data->longjmp_msym[i].minsym))
+       continue;
+
+      func_name = longjmp_names[i];
+      if (bp_objfile_data->longjmp_msym[i].minsym == NULL)
+       {
+         struct bound_minimal_symbol m;
+
+         m = lookup_minimal_symbol_text (func_name, objfile);
+         if (m.minsym == NULL)
+           {
+             /* Prevent future lookups in this objfile.  */
+             bp_objfile_data->longjmp_msym[i].minsym = &msym_not_found;
              continue;
            }
+         bp_objfile_data->longjmp_msym[i] = m;
+       }
 
-         if (!gdbarch_get_longjmp_target_p (gdbarch))
-           continue;
+      addr = BMSYMBOL_VALUE_ADDRESS (bp_objfile_data->longjmp_msym[i]);
+      b = create_internal_breakpoint (gdbarch, addr, bp_longjmp_master,
+                                     &internal_breakpoint_ops);
+      initialize_explicit_location (&explicit_loc);
+      explicit_loc.function_name = ASTRDUP (func_name);
+      b->location = new_explicit_location (&explicit_loc);
+      b->enable_state = bp_disabled;
+      installed_bp++;
+    }
 
-         for (i = 0; i < NUM_LONGJMP_NAMES; i++)
-           {
-             struct breakpoint *b;
-             const char *func_name;
-             CORE_ADDR addr;
-             struct explicit_location explicit_loc;
+  return installed_bp > 0;
+}
 
-             if (msym_not_found_p (bp_objfile_data->longjmp_msym[i].minsym))
-               continue;
+/* Create a master longjmp breakpoint.  */
 
-             func_name = longjmp_names[i];
-             if (bp_objfile_data->longjmp_msym[i].minsym == NULL)
-               {
-                 struct bound_minimal_symbol m;
+static void
+create_longjmp_master_breakpoint (void)
+{
+  scoped_restore_current_program_space restore_pspace;
 
-                 m = lookup_minimal_symbol_text (func_name, objfile);
-                 if (m.minsym == NULL)
-                   {
-                     /* Prevent future lookups in this objfile.  */
-                     bp_objfile_data->longjmp_msym[i].minsym = &msym_not_found;
-                     continue;
-                   }
-                 bp_objfile_data->longjmp_msym[i] = m;
-               }
+  for (struct program_space *pspace : program_spaces)
+    {
+      set_current_program_space (pspace);
 
-             addr = BMSYMBOL_VALUE_ADDRESS (bp_objfile_data->longjmp_msym[i]);
-             b = create_internal_breakpoint (gdbarch, addr, bp_longjmp_master,
-                                             &internal_breakpoint_ops);
-             initialize_explicit_location (&explicit_loc);
-             explicit_loc.function_name = ASTRDUP (func_name);
-             b->location = new_explicit_location (&explicit_loc);
-             b->enable_state = bp_disabled;
-           }
+      for (objfile *obj : current_program_space->objfiles ())
+       {
+         /* Skip separate debug object, it's handled in the loop below.  */
+         if (obj->separate_debug_objfile_backlink != nullptr)
+           continue;
+
+         /* Try a probe kind breakpoint on main objfile.  */
+         if (create_longjmp_master_breakpoint_probe (obj))
+           continue;
+
+         /* Try longjmp_names kind breakpoints on main and separate_debug
+            objfiles.  */
+         for (objfile *debug_objfile : obj->separate_debug_objfiles ())
+           if (create_longjmp_master_breakpoint_names (debug_objfile))
+             break;
        }
     }
 }
@@ -3479,92 +3511,126 @@ create_std_terminate_master_breakpoint (void)
     }
 }
 
-/* Install a master breakpoint on the unwinder's debug hook.  */
+/* Install a master breakpoint on the unwinder's debug hook for OBJFILE using a
+   probe.  Return true if a breakpoint was installed.  */
 
-static void
-create_exception_master_breakpoint (void)
+static bool
+create_exception_master_breakpoint_probe (objfile *objfile)
 {
-  const char *const func_name = "_Unwind_DebugHook";
+  struct breakpoint *b;
+  struct gdbarch *gdbarch;
+  struct breakpoint_objfile_data *bp_objfile_data;
 
-  for (objfile *objfile : current_program_space->objfiles ())
-    {
-      struct breakpoint *b;
-      struct gdbarch *gdbarch;
-      struct breakpoint_objfile_data *bp_objfile_data;
-      CORE_ADDR addr;
-      struct explicit_location explicit_loc;
+  bp_objfile_data = get_breakpoint_objfile_data (objfile);
 
-      bp_objfile_data = get_breakpoint_objfile_data (objfile);
+  /* We prefer the SystemTap probe point if it exists.  */
+  if (!bp_objfile_data->exception_searched)
+    {
+      std::vector<probe *> ret
+       = find_probes_in_objfile (objfile, "libgcc", "unwind");
 
-      /* We prefer the SystemTap probe point if it exists.  */
-      if (!bp_objfile_data->exception_searched)
+      if (!ret.empty ())
        {
-         std::vector<probe *> ret
-           = find_probes_in_objfile (objfile, "libgcc", "unwind");
+         /* We are only interested in checking one element.  */
+         probe *p = ret[0];
 
-         if (!ret.empty ())
+         if (!p->can_evaluate_arguments ())
            {
-             /* We are only interested in checking one element.  */
-             probe *p = ret[0];
-
-             if (!p->can_evaluate_arguments ())
-               {
-                 /* We cannot use the probe interface here, because it does
-                    not know how to evaluate arguments.  */
-                 ret.clear ();
-               }
+             /* We cannot use the probe interface here, because it does
+                not know how to evaluate arguments.  */
+             ret.clear ();
            }
-         bp_objfile_data->exception_probes = ret;
-         bp_objfile_data->exception_searched = 1;
        }
+      bp_objfile_data->exception_probes = ret;
+      bp_objfile_data->exception_searched = 1;
+    }
 
-      if (!bp_objfile_data->exception_probes.empty ())
-       {
-         gdbarch = objfile->arch ();
+  if (bp_objfile_data->exception_probes.empty ())
+    return false;
 
-         for (probe *p : bp_objfile_data->exception_probes)
-           {
-             b = create_internal_breakpoint (gdbarch,
-                                             p->get_relocated_address (objfile),
-                                             bp_exception_master,
-                                             &internal_breakpoint_ops);
-             b->location = new_probe_location ("-probe-stap libgcc:unwind");
-             b->enable_state = bp_disabled;
-           }
+  gdbarch = objfile->arch ();
 
-         continue;
-       }
+  for (probe *p : bp_objfile_data->exception_probes)
+    {
+      b = create_internal_breakpoint (gdbarch,
+                                     p->get_relocated_address (objfile),
+                                     bp_exception_master,
+                                     &internal_breakpoint_ops);
+      b->location = new_probe_location ("-probe-stap libgcc:unwind");
+      b->enable_state = bp_disabled;
+    }
+
+  return true;
+}
 
-      /* Otherwise, try the hook function.  */
+/* Install a master breakpoint on the unwinder's debug hook for OBJFILE using
+   _Unwind_DebugHook.  Return true if a breakpoint was installed.  */
 
-      if (msym_not_found_p (bp_objfile_data->exception_msym.minsym))
-       continue;
+static bool
+create_exception_master_breakpoint_hook (objfile *objfile)
+{
+  const char *const func_name = "_Unwind_DebugHook";
+  struct breakpoint *b;
+  struct gdbarch *gdbarch;
+  struct breakpoint_objfile_data *bp_objfile_data;
+  CORE_ADDR addr;
+  struct explicit_location explicit_loc;
 
-      gdbarch = objfile->arch ();
+  bp_objfile_data = get_breakpoint_objfile_data (objfile);
 
-      if (bp_objfile_data->exception_msym.minsym == NULL)
-       {
-         struct bound_minimal_symbol debug_hook;
+  if (msym_not_found_p (bp_objfile_data->exception_msym.minsym))
+    return false;
 
-         debug_hook = lookup_minimal_symbol (func_name, NULL, objfile);
-         if (debug_hook.minsym == NULL)
-           {
-             bp_objfile_data->exception_msym.minsym = &msym_not_found;
-             continue;
-           }
+  gdbarch = objfile->arch ();
+
+  if (bp_objfile_data->exception_msym.minsym == NULL)
+    {
+      struct bound_minimal_symbol debug_hook;
 
-         bp_objfile_data->exception_msym = debug_hook;
+      debug_hook = lookup_minimal_symbol (func_name, NULL, objfile);
+      if (debug_hook.minsym == NULL)
+       {
+         bp_objfile_data->exception_msym.minsym = &msym_not_found;
+         return false;
        }
 
-      addr = BMSYMBOL_VALUE_ADDRESS (bp_objfile_data->exception_msym);
-      addr = gdbarch_convert_from_func_ptr_addr (gdbarch, addr,
-                                                current_top_target ());
-      b = create_internal_breakpoint (gdbarch, addr, bp_exception_master,
-                                     &internal_breakpoint_ops);
-      initialize_explicit_location (&explicit_loc);
-      explicit_loc.function_name = ASTRDUP (func_name);
-      b->location = new_explicit_location (&explicit_loc);
-      b->enable_state = bp_disabled;
+      bp_objfile_data->exception_msym = debug_hook;
+    }
+
+  addr = BMSYMBOL_VALUE_ADDRESS (bp_objfile_data->exception_msym);
+  addr = gdbarch_convert_from_func_ptr_addr (gdbarch, addr,
+                                            current_top_target ());
+  b = create_internal_breakpoint (gdbarch, addr, bp_exception_master,
+                                 &internal_breakpoint_ops);
+  initialize_explicit_location (&explicit_loc);
+  explicit_loc.function_name = ASTRDUP (func_name);
+  b->location = new_explicit_location (&explicit_loc);
+  b->enable_state = bp_disabled;
+
+  return true;
+}
+
+/* Install a master breakpoint on the unwinder's debug hook.  */
+
+static void
+create_exception_master_breakpoint (void)
+{
+  for (objfile *obj : current_program_space->objfiles ())
+    {
+      /* Skip separate debug object.  */
+      if (obj->separate_debug_objfile_backlink)
+       continue;
+
+      /* Try a probe kind breakpoint.  */
+      if (create_exception_master_breakpoint_probe (obj))
+       continue;
+
+      /* Iterate over separate debug objects and try an _Unwind_DebugHook
+        kind breakpoint.  */
+      for (objfile *sepdebug = obj->separate_debug_objfile;
+          sepdebug != nullptr; sepdebug = sepdebug->separate_debug_objfile)
+       if (create_exception_master_breakpoint_hook (sepdebug))
+         break;
     }
 }
 
@@ -4242,15 +4308,6 @@ is_catchpoint (struct breakpoint *b)
   return (b->type == bp_catchpoint);
 }
 
-/* Frees any storage that is part of a bpstat.  Does not walk the
-   'next' chain.  */
-
-bpstats::~bpstats ()
-{
-  if (bp_location_at != NULL)
-    decref_bp_location (&bp_location_at);
-}
-
 /* Clear a bpstat so that it says we are not at any breakpoint.
    Also free any storage that is part of a bpstat.  */
 
@@ -4283,7 +4340,6 @@ bpstats::bpstats (const bpstats &other)
 {
   if (other.old_val != NULL)
     old_val = release_value (value_copy (other.old_val.get ()));
-  incref_bp_location (bp_location_at);
 }
 
 /* Return a copy of a bpstat.  Like "bs1 = bs2" but all storage that
@@ -4768,21 +4824,19 @@ breakpoint_cond_eval (expression *exp)
 
 bpstats::bpstats (struct bp_location *bl, bpstat **bs_link_pointer)
   : next (NULL),
-    bp_location_at (bl),
+    bp_location_at (bp_location_ref_ptr::new_reference (bl)),
     breakpoint_at (bl->owner),
     commands (NULL),
     print (0),
     stop (0),
     print_it (print_it_normal)
 {
-  incref_bp_location (bl);
   **bs_link_pointer = this;
   *bs_link_pointer = &next;
 }
 
 bpstats::bpstats ()
   : next (NULL),
-    bp_location_at (NULL),
     breakpoint_at (NULL),
     commands (NULL),
     print (0),
@@ -5060,7 +5114,7 @@ bpstat_check_watchpoint (bpstat bs)
   struct watchpoint *b;
 
   /* BS is built for existing struct breakpoint.  */
-  bl = bs->bp_location_at;
+  bl = bs->bp_location_at.get ();
   gdb_assert (bl != NULL);
   b = (struct watchpoint *) bs->breakpoint_at;
   gdb_assert (b != NULL);
@@ -5236,7 +5290,7 @@ bpstat_check_breakpoint_conditions (bpstat bs, thread_info *thread)
   gdb_assert (bs->stop);
 
   /* BS is built for existing struct breakpoint.  */
-  bl = bs->bp_location_at;
+  bl = bs->bp_location_at.get ();
   gdb_assert (bl != NULL);
   b = bs->breakpoint_at;
   gdb_assert (b != NULL);
@@ -7101,7 +7155,7 @@ bp_location::bp_location (breakpoint *owner, bp_loc_type type)
       || this->loc_type == bp_loc_hardware_breakpoint)
     mark_breakpoint_location_modified (this);
 
-  this->refc = 1;
+  incref ();
 }
 
 bp_location::bp_location (breakpoint *owner)
@@ -7118,30 +7172,13 @@ allocate_bp_location (struct breakpoint *bpt)
   return bpt->ops->allocate_location (bpt);
 }
 
-static void
-free_bp_location (struct bp_location *loc)
-{
-  delete loc;
-}
-
-/* Increment reference count.  */
-
-static void
-incref_bp_location (struct bp_location *bl)
-{
-  ++bl->refc;
-}
-
 /* Decrement reference count.  If the reference count reaches 0,
    destroy the bp_location.  Sets *BLP to NULL.  */
 
 static void
 decref_bp_location (struct bp_location **blp)
 {
-  gdb_assert ((*blp)->refc > 0);
-
-  if (--(*blp)->refc == 0)
-    free_bp_location (*blp);
+  bp_location_ref_policy::decref (*blp);
   *blp = NULL;
 }
 
@@ -9263,7 +9300,7 @@ find_condition_and_thread (const char *tok, CORE_ADDR pc,
        }
       else if (toklen >= 1 && strncmp (tok, "-force-condition", toklen) == 0)
        {
-         tok = cond_start = end_tok + 1;
+         tok = tok + toklen;
          force = true;
        }
       else if (toklen >= 1 && strncmp (tok, "thread", toklen) == 0)
@@ -12680,7 +12717,7 @@ bkpt_print_it (bpstat bs)
 
   gdb_assert (bs->bp_location_at != NULL);
 
-  bl = bs->bp_location_at;
+  bl = bs->bp_location_at.get ();
   b = bs->breakpoint_at;
 
   bp_temp = b->disposition == disp_del;
This page took 0.031722 seconds and 4 git commands to generate.