From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 43096 invoked by alias); 11 Apr 2017 23:51:17 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 43078 invoked by uid 89); 11 Apr 2017 23:51:16 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,RP_MATCHES_RCVD,SPF_HELO_PASS autolearn=ham version=3.3.2 spammy=Ie, I.e, UD:I.e X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 11 Apr 2017 23:51:14 +0000 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 5995083F40 for ; Tue, 11 Apr 2017 23:51:15 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 5995083F40 Authentication-Results: ext-mx03.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx03.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=palves@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 5995083F40 Received: from cascais.lan (ovpn04.gateway.prod.ext.phx2.redhat.com [10.5.9.4]) by smtp.corp.redhat.com (Postfix) with ESMTP id DF11917C3C for ; Tue, 11 Apr 2017 23:51:14 +0000 (UTC) From: Pedro Alves To: gdb-patches@sourceware.org Subject: [PATCH 1/8] watch_command_1: Fix dangling frame access Date: Tue, 11 Apr 2017 23:51:00 -0000 Message-Id: <1491954673-29172-2-git-send-email-palves@redhat.com> In-Reply-To: <1491954673-29172-1-git-send-email-palves@redhat.com> References: <1491954673-29172-1-git-send-email-palves@redhat.com> X-SW-Source: 2017-04/txt/msg00297.txt.bz2 While working on some changes to switch_to_thread, I inadvertently make switch_to_thread call reinit_frame_cache more frequently, even when the thread didn't change. This exposed a latent bug in watch_command_1, where we're referencing a frame after creating/inserting breakpoints, which potentially calls reinit_frame_cache if it needs to install breakpoints with a different thread selected. Handle this similarly to how it's already handled in other similar cases. I.e., save any frame-related information we might need before creating a breakpoint. gdb/ChangeLog: yyyy-mm-dd Pedro Alves * breakpoint.c (watch_command_1): Save watchpoint-frame info before calling create_internal_breakpoint. --- gdb/breakpoint.c | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 3925ec6..b2f6d6e 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -11100,7 +11100,6 @@ watch_command_1 (const char *arg, int accessflag, int from_tty, const struct block *exp_valid_block = NULL, *cond_exp_valid_block = NULL; struct value *val, *mark, *result; int saved_bitpos = 0, saved_bitsize = 0; - struct frame_info *frame; const char *exp_start = NULL; const char *exp_end = NULL; const char *tok, *end_tok; @@ -11278,35 +11277,44 @@ watch_command_1 (const char *arg, int accessflag, int from_tty, if (*tok) error (_("Junk at end of command.")); - frame = block_innermost_frame (exp_valid_block); + frame_info *wp_frame = block_innermost_frame (exp_valid_block); + + /* Save this because create_internal_breakpoint below invalidates + 'wp_frame'. */ + frame_id watchpoint_frame = get_frame_id (wp_frame); /* If the expression is "local", then set up a "watchpoint scope" breakpoint at the point where we've left the scope of the watchpoint expression. Create the scope breakpoint before the watchpoint, so that we will encounter it first in bpstat_stop_status. */ - if (exp_valid_block && frame) + if (exp_valid_block && wp_frame) { - if (frame_id_p (frame_unwind_caller_id (frame))) + struct frame_id caller_frame_id = frame_unwind_caller_id (wp_frame); + + if (frame_id_p (caller_frame_id)) { + gdbarch *caller_arch = frame_unwind_caller_arch (wp_frame); + CORE_ADDR caller_pc = frame_unwind_caller_pc (wp_frame); + scope_breakpoint - = create_internal_breakpoint (frame_unwind_caller_arch (frame), - frame_unwind_caller_pc (frame), + = create_internal_breakpoint (caller_arch, caller_pc, bp_watchpoint_scope, &momentary_breakpoint_ops); + /* create_internal_breakpoint could invalidate WP_FRAME. */ + wp_frame = NULL; + scope_breakpoint->enable_state = bp_enabled; /* Automatically delete the breakpoint when it hits. */ scope_breakpoint->disposition = disp_del; /* Only break in the proper frame (help with recursion). */ - scope_breakpoint->frame_id = frame_unwind_caller_id (frame); + scope_breakpoint->frame_id = caller_frame_id; /* Set the address at which we will stop. */ - scope_breakpoint->loc->gdbarch - = frame_unwind_caller_arch (frame); - scope_breakpoint->loc->requested_address - = frame_unwind_caller_pc (frame); + scope_breakpoint->loc->gdbarch = caller_arch; + scope_breakpoint->loc->requested_address = caller_pc; scope_breakpoint->loc->address = adjust_breakpoint_address (scope_breakpoint->loc->gdbarch, scope_breakpoint->loc->requested_address, @@ -11378,9 +11386,9 @@ watch_command_1 (const char *arg, int accessflag, int from_tty, else b->cond_string = 0; - if (frame) + if (frame_id_p (watchpoint_frame)) { - w->watchpoint_frame = get_frame_id (frame); + w->watchpoint_frame = watchpoint_frame; w->watchpoint_thread = inferior_ptid; } else -- 2.5.5