From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 37670 invoked by alias); 29 Aug 2018 17:29:10 -0000 Mailing-List: contact gdb-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-owner@sourceware.org Received: (qmail 37655 invoked by uid 89); 29 Aug 2018 17:29:10 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-2.8 required=5.0 tests=AWL,BAYES_00,SPF_HELO_PASS autolearn=ham version=3.3.2 spammy=nowadays X-HELO: mx1.redhat.com Received: from mx3-rdu2.redhat.com (HELO mx1.redhat.com) (66.187.233.73) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 29 Aug 2018 17:29:09 +0000 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 73A8D77886; Wed, 29 Aug 2018 17:29:07 +0000 (UTC) Received: from [127.0.0.1] (ovpn04.gateway.prod.ext.ams2.redhat.com [10.39.146.4]) by smtp.corp.redhat.com (Postfix) with ESMTP id 62CAF2026D6D; Wed, 29 Aug 2018 17:29:06 +0000 (UTC) Subject: Re: gdb requires watchpoints to fire after the write To: Simon Marchi , Joel Brobecker References: <3833782b96d47551263798eb78f448bd@polymtl.ca> <20180829154739.GB2521@adacore.com> Cc: Tim Newsome , gdb From: Pedro Alves Message-ID: <08cf0b78-0fe6-1eda-383f-7d64466d6381@redhat.com> Date: Wed, 29 Aug 2018 17:29:00 -0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.8.0 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-SW-Source: 2018-08/txt/msg00052.txt.bz2 On 08/29/2018 05:02 PM, Simon Marchi wrote: > I'm just confused by this condition: > >   if (stopped_by_watchpoint >       && (target_have_steppable_watchpoint >       || gdbarch_have_nonsteppable_watchpoint (gdbarch))) > > I don't understand why we check for target_have_steppable_watchpoint OR gdbarch_have_nonsteppable_watchpoint, they seem to mean opposite things. Yeah, it's confusing. GDB's current "model" is that there are three "kinds" of watchpoints, wrt to when they trigger and how you can move past them. Those are: continuable, steppable, and non-steppable. Continuable watchpoints are like x86's -- those trigger after the memory access's side effects are fully committed to memory. I.e., they trap with the PC pointing at the next instruction already. Continuing past such a watchpoint is doable by just normally continuing, hence the name. Both steppable and nonsteppable watchpoints trap before the memory access. I.e, the PC points at the instruction that is accessing the memory. So GDB needs to single-step once past the current instruction in order to make the access effective and check whether the instruction's side effects change the watched expression. Now, in order to step past that instruction, depending on architecture, you can have two situations: - steppable watchpoints: you can single-step with the watchpoint still armed, and the watchpoint won't trigger again. - non-steppable watchpoints: if you try to single-step with the watchpoint still armed, you'd trap the watchpoint again and the thread wouldn't make any progress. So GDB needs to temporarily remove the watchpoint in order to step past it. So that's why we have all of target_have_continuable_watchpoint, target_have_steppable_watchpoint and gdbarch_have_nonsteppable_watchpoint. Now, the main oddity is that from the definitions above, we can tell that "continuable" is the same as "!steppable && !nonsteppable", which makes target_continuable_watchpoint redundant. Some targets do set "have_continuable_watchpoint" (like x86 in x86-nat.h), but it doesn't seem like target_have_continuable_watchpoint is checked anywhere nowadays. The target_have_steppable_watchpoint property is only set by ia64 GNU/Linux nowadays: /* The IA-64 architecture can step over a watch point (without triggering it again) if the "dd" (data debug fault disable) bit in the processor status word is set. This PSR bit is set in ia64_linux_nat_target::stopped_by_watchpoint when the code there has determined that a hardware watchpoint has indeed been hit. The CPU will then be able to execute one instruction without triggering a watchpoint. */ bool have_steppable_watchpoint () { return 1; } There's of course also the oddity that target_have_continuable_watchpoint and target_have_steppable_watchpoint are target methods, while gdbarch_have_nonsteppable_watchpoint is a gdbarch method... We could most probably streamline all of this and come up with a better design with some thought. See also the comment in mips-tdep.c: /* FIXME: cagney/2003-08-29: The macros target_have_steppable_watchpoint, HAVE_NONSTEPPABLE_WATCHPOINT, and target_have_continuable_watchpoint need to all be folded into the target vector. Since they are being used as guards for target_stopped_by_watchpoint, why not have target_stopped_by_watchpoint return the type of watchpoint that the code is sitting on? */ set_gdbarch_have_nonsteppable_watchpoint (gdbarch, 1); Thanks, Pedro Alves