From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id uTUXGWDs919IIgAAWB0awg (envelope-from ) for ; Fri, 08 Jan 2021 00:23:44 -0500 Received: by simark.ca (Postfix, from userid 112) id 547A11E99A; Fri, 8 Jan 2021 00:23:44 -0500 (EST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on simark.ca X-Spam-Level: X-Spam-Status: No, score=0.3 required=5.0 tests=MAILING_LIST_MULTI,RDNS_NONE, URIBL_BLOCKED autolearn=no autolearn_force=no version=3.4.2 Received: from sourceware.org (unknown [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by simark.ca (Postfix) with ESMTPS id 6EC1E1E4F4; Fri, 8 Jan 2021 00:23:43 -0500 (EST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 18BD73851C17; Fri, 8 Jan 2021 05:23:43 +0000 (GMT) Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) by sourceware.org (Postfix) with ESMTPS id 620E83851C17 for ; Fri, 8 Jan 2021 05:23:38 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 620E83851C17 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=suse.de Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=tdevries@suse.de X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 55C63AD11; Fri, 8 Jan 2021 05:23:37 +0000 (UTC) Subject: Re: [PATCH][gdb] Fix internal-error in process_event_stop_test To: Tom Tromey References: <20210105132923.GA15843@delia> <87y2h4v77m.fsf@tromey.com> From: Tom de Vries Message-ID: Date: Fri, 8 Jan 2021 06:23:36 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.5.0 MIME-Version: 1.0 In-Reply-To: <87y2h4v77m.fsf@tromey.com> Content-Type: multipart/mixed; boundary="------------29C7C247F622853C93635EB6" Content-Language: en-US X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: gdb-patches@sourceware.org Errors-To: gdb-patches-bounces@sourceware.org Sender: "Gdb-patches" This is a multi-part message in MIME format. --------------29C7C247F622853C93635EB6 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit On 1/7/21 9:10 PM, Tom Tromey wrote: >>>>>> "Tom" == Tom de Vries writes: > > Tom> Fix this by only trying to install the master exception breakpoint in > Tom> libgcc.debug using the _Unwind_DebugHook method, if the install using probes > Tom> in libgcc failed. > > This seems like a reasonable idea. > > Tom> Any comments? > > I suspect this would be a bit shorter if the loop only examined > "primary" objfiles (ones that don't have a backlink) and then delegated > to a helper function that did the search. What do you think? I've made the loop now over "primary" objfiles. Also, I've split up the helper function into one using probes, and the other using the hook, which hopefully helps to make the code a bit clearer. I'll put this through testing and commit, unless there are further comments. Thanks, - Tom --------------29C7C247F622853C93635EB6 Content-Type: text/x-patch; charset=UTF-8; name="0001-gdb-Fix-internal-error-in-process_event_stop_test.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename*0="0001-gdb-Fix-internal-error-in-process_event_stop_test.patch" [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-05 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. --- gdb/breakpoint.c | 164 +++++++++++++++++++++++++++++++++---------------------- 1 file changed, 99 insertions(+), 65 deletions(-) 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; } } --------------29C7C247F622853C93635EB6--