[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