- Replace tentative fix with upstreamed fix [swo#26881]: Remove: * gdb-fix-assert-in-process-event-stop-test.patch Add: * gdb-fix-internal-error-in-process_event_stop_test.patch * gdb-breakpoints-handle-glibc-with-debuginfo-in-create_exception_master_breakpoint.patch - Fix license [bsc#1180786]. OBS-URL: https://build.opensuse.org/request/show/872638 OBS-URL: https://build.opensuse.org/package/show/devel:gcc/gdb?expand=0&rev=269
268 lines
8.7 KiB
Diff
268 lines
8.7 KiB
Diff
[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;
|
|
}
|
|
}
|
|
|