File gdb-fix-internal-error-in-process_event_stop_test.patch of Package gdb.18935

[gdb] Fix internal-error in process_event_stop_test

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.

gdb/ChangeLog:

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

	PR gdb/26881
	* breakpoint.c (create_exception_master_breakpoint_probe)
	(create_exception_master_breakpoint_hook): 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 | 164 +++++++++++++++++++++++++++++++++----------------------
 2 files changed, 110 insertions(+), 65 deletions(-)

diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index f304c0c3559..7ead1529ad1 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -3360,92 +3360,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;
 
-	  bp_objfile_data->exception_msym = debug_hook;
+  gdbarch = objfile->arch ();
+
+  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;
     }
 }
 
openSUSE Build Service is sponsored by