diff options
author | Tom de Vries <tdevries@suse.de> | 2021-01-08 11:11:16 +0100 |
---|---|---|
committer | Tom de Vries <tdevries@suse.de> | 2021-01-08 11:11:16 +0100 |
commit | 1940319c0ef6271cc42a5d4c359be90063948710 (patch) | |
tree | 318ea63963a6b6cb6b6726487e9e4fc31150c637 /gdb | |
parent | e343681375c1e5a27ea92486649f6a58163c0e61 (diff) | |
download | binutils-1940319c0ef6271cc42a5d4c359be90063948710.zip binutils-1940319c0ef6271cc42a5d4c359be90063948710.tar.gz binutils-1940319c0ef6271cc42a5d4c359be90063948710.tar.bz2 |
[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.
Diffstat (limited to 'gdb')
-rw-r--r-- | gdb/ChangeLog | 11 | ||||
-rw-r--r-- | gdb/breakpoint.c | 164 |
2 files changed, 110 insertions, 65 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index f01a142..32ece30 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,14 @@ +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. + 2021-01-08 Andrew Burgess <andrew.burgess@embecosm.com> * f-lang.c (fortran_value_subarray): Call value_from_component. diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 69e4529..70a4d0e 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -3477,92 +3477,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. */ + +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; - gdbarch = objfile->arch (); + bp_objfile_data = get_breakpoint_objfile_data (objfile); - if (bp_objfile_data->exception_msym.minsym == NULL) - { - struct bound_minimal_symbol debug_hook; + if (msym_not_found_p (bp_objfile_data->exception_msym.minsym)) + 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; - } + gdbarch = objfile->arch (); + + if (bp_objfile_data->exception_msym.minsym == NULL) + { + struct bound_minimal_symbol debug_hook; - bp_objfile_data->exception_msym = 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; } } |