From: Tom de Vries Date: Fri, 8 Jan 2021 10:11:16 +0000 (+0100) Subject: [gdb] Fix internal-error in process_event_stop_test X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=1940319c0ef;p=binutils-gdb.git [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 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. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index f01a1428804..32ece3020a2 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,14 @@ +2021-01-08 Tom de Vries + + 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 * f-lang.c (fortran_value_subarray): Call value_from_component. diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 69e452993f1..70a4d0e1690 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 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 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; } }