[gdb/breakpoints] Fix longjmp master breakpoint with separate debug info
[deliverable/binutils-gdb.git] / gdb / breakpoint.c
index 69e452993f1cc5116497ca59a79a1b178d5b2c44..70b0d88cb45aedcf24a389e6bbfcbee0c926a8c4 100644 (file)
@@ -3327,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;
        }
     }
 }
@@ -3477,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;
+    }
 
-      /* Otherwise, try the hook function.  */
+  return true;
+}
 
-      if (msym_not_found_p (bp_objfile_data->exception_msym.minsym))
-       continue;
+/* Install a master breakpoint on the unwinder's debug hook for OBJFILE using
+   _Unwind_DebugHook.  Return true if a breakpoint was installed.  */
 
-      gdbarch = objfile->arch ();
+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;
 
-      if (bp_objfile_data->exception_msym.minsym == NULL)
-       {
-         struct bound_minimal_symbol debug_hook;
+  bp_objfile_data = get_breakpoint_objfile_data (objfile);
 
-         debug_hook = lookup_minimal_symbol (func_name, NULL, objfile);
-         if (debug_hook.minsym == NULL)
-           {
-             bp_objfile_data->exception_msym.minsym = &msym_not_found;
-             continue;
-           }
+  if (msym_not_found_p (bp_objfile_data->exception_msym.minsym))
+    return false;
+
+  gdbarch = objfile->arch ();
 
-         bp_objfile_data->exception_msym = debug_hook;
+  if (bp_objfile_data->exception_msym.minsym == NULL)
+    {
+      struct bound_minimal_symbol 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;
     }
 }
 
This page took 0.029011 seconds and 4 git commands to generate.