[PATCH][gdb] Fix internal-error in process_event_stop_test

Tom de Vries tdevries@suse.de
Tue Jan 5 13:29:24 GMT 2021


Hi,

The function create_exception_master_breakpoint in gdb/breakpoint.c attempts
to set a master exception breakpoint in each objfile.  It tries this using
a libgcc/unwind probe, and if that fails then using the
_Unwind_DebugHook symbol:
...
   for (objfile *objfile : current_program_space->objfiles ())
     {
        /* Try using probes.  */
        if (/* successful */)
          continue;

        /* Try using _Unwind_DebugHook */
     }
...

The preference scheme works ok both if the objfile has debug info, and if it's
stripped.

But it doesn't work when the objfile has a .gnu_debuglink to a .debug file
(and the .debug file is present).  What happens is that:
- we first encounter objfile libgcc.debug
- we try using probes, and this fails
- so we try _Unwind_DebugHook, which succeeds
- next we encounter objfile libgcc
- we try using probes, and this succeeds.
So, we end up with a master exception breakpoint in both libgcc (using probes)
and libgcc.debug (using _Unwind_DebugHook).

This eventually causes:
...
(gdb) PASS: gdb.cp/nextoverthrow.exp: post-check - next over a throw 3
next^M
src/gdb/infrun.c:6384: internal-error: \
  void process_event_stop_test(execution_control_state*): \
  Assertion `ecs->event_thread->control.exception_resume_breakpoint != NULL' \
  failed.^M
A problem internal to GDB has been detected,^M
further debugging may prove unreliable.^M
Quit this debugging session? (y or n) FAIL: gdb.cp/nextoverthrow.exp: next
past catch (GDB internal error)
...

To trigger this internal-error, we need to use gcc-10 or later to compile the
test-case, such that it contains the fix for gcc PR97774 - "Incorrect line
info for try/catch".

Fix this by only trying to install the master exception breakpoint in
libgcc.debug using the _Unwind_DebugHook method, if the install using probes
in libgcc failed.

Tested on x86_64-linux.

Any comments?

Thanks,
- Tom

[gdb] Fix internal-error in process_event_stop_test

gdb/ChangeLog:

2021-01-05  Tom de Vries  <tdevries@suse.de>

	PR gdb/26881
	* breakpoint.c (create_exception_master_breakpoint_1): Factor out
	of ...
	(create_exception_master_breakpoint): ... here.  Only try to install
	the master exception breakpoint in objfile.debug using the
	_Unwind_DebugHook method, if the install using probes in objfile
	failed.

---
 gdb/breakpoint.c | 155 +++++++++++++++++++++++++++++++++----------------------
 1 file changed, 93 insertions(+), 62 deletions(-)

diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 69e452993f1..6171e9ca396 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -3477,92 +3477,123 @@ 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.
+   Return true if a breakpoint was installed.  */
 
-static void
-create_exception_master_breakpoint (void)
+static bool
+create_exception_master_breakpoint_1 (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;
 
-  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 ())
+  if (!bp_objfile_data->exception_probes.empty ())
+    {
+      gdbarch = objfile->arch ();
+
+      for (probe *p : bp_objfile_data->exception_probes)
 	{
-	  gdbarch = objfile->arch ();
+	  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;
+	}
 
-	  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;
+    }
 
-	  continue;
-	}
+  /* Otherwise, try the hook function.  */
 
-      /* Otherwise, try the hook function.  */
+  if (msym_not_found_p (bp_objfile_data->exception_msym.minsym))
+    return false;
 
-      if (msym_not_found_p (bp_objfile_data->exception_msym.minsym))
-	continue;
+  gdbarch = objfile->arch ();
 
-      gdbarch = objfile->arch ();
+  if (bp_objfile_data->exception_msym.minsym == NULL)
+    {
+      struct bound_minimal_symbol debug_hook;
 
-      if (bp_objfile_data->exception_msym.minsym == NULL)
+      debug_hook = lookup_minimal_symbol (func_name, NULL, objfile);
+      if (debug_hook.minsym == NULL)
 	{
-	  struct bound_minimal_symbol debug_hook;
+	  bp_objfile_data->exception_msym.minsym = &msym_not_found;
+	  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;
-	    }
+      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.  */
 
-	  bp_objfile_data->exception_msym = debug_hook;
+static void
+create_exception_master_breakpoint (void)
+{
+  objfile *skip = nullptr;
+  for (objfile *obj : current_program_space->objfiles ())
+    {
+      if (skip)
+	{
+	  gdb_assert (skip == obj);
+	  skip = nullptr;
+	  continue;
 	}
 
-      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;
+      if (obj->separate_debug_objfile_backlink)
+	{
+	  objfile *exec = obj->separate_debug_objfile_backlink;
+
+	  /* Try a probe kind breakpoint in the exec objfile.  */
+	  if (!create_exception_master_breakpoint_1 (exec))
+	    /* Try an _Unwind_DebugHook kind breakpoint in the .debug
+	       objfile.  */
+	    create_exception_master_breakpoint_1 (obj);
+
+	  skip = exec;
+	}
+      else
+	create_exception_master_breakpoint_1 (obj);
     }
 }
 


More information about the Gdb-patches mailing list