From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 31625 invoked by alias); 30 Nov 2011 18:24:10 -0000 Received: (qmail 31613 invoked by uid 22791); 30 Nov 2011 18:24:08 -0000 X-SWARE-Spam-Status: No, hits=-1.6 required=5.0 tests=AWL,BAYES_00,FROM_12LTRDOM X-Spam-Check-By: sourceware.org Received: from relay1.mentorg.com (HELO relay1.mentorg.com) (192.94.38.131) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 30 Nov 2011 18:23:54 +0000 Received: from svr-orw-fem-01.mgc.mentorg.com ([147.34.98.93]) by relay1.mentorg.com with esmtp id 1RVooz-0006Et-GE from Maciej_Rozycki@mentor.com for gdb-patches@sourceware.org; Wed, 30 Nov 2011 10:23:53 -0800 Received: from SVR-IES-FEM-01.mgc.mentorg.com ([137.202.0.104]) by svr-orw-fem-01.mgc.mentorg.com over TLS secured channel with Microsoft SMTPSVC(6.0.3790.4675); Wed, 30 Nov 2011 10:23:53 -0800 Received: from [172.30.5.250] (137.202.0.76) by SVR-IES-FEM-01.mgc.mentorg.com (137.202.0.104) with Microsoft SMTP Server id 14.1.289.1; Wed, 30 Nov 2011 18:23:50 +0000 Date: Wed, 30 Nov 2011 18:24:00 -0000 From: "Maciej W. Rozycki" To: Subject: [PATCH] remote: Fix hw watchpoint address matching Message-ID: User-Agent: Alpine 1.10 (DEB 962 2008-03-14) MIME-Version: 1.0 Content-Type: text/plain; charset="US-ASCII" 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 X-SW-Source: 2011-11/txt/msg00852.txt.bz2 Hi, There is a problem in the remote target where watchpoint addresses are masked before they are passed on to the target, but later on if such a watchpoint is hit the generic range-checker compares the masked address reported by the remote side with the original unmasked address associated with the watchpoint within GDB. The result for 32-bit MIPS processors and KSEG addresses, which are sign-extended to 64 bits and thus non-zero in the 32 high order bits, is the watchpoint hit is not recognised and a SIGTRAP reported instead. The fix below replaces the generic checker with a specific one that applies the mask for the purpose of the range check. This is imperfect if "set remoteaddresssize" was used to set the mask beyond the width of the address used by the target, but I think it's about as reasonable as you can get. And the setting looks like an awful hack to me, so my suggestion is merely: "Don't do it." Regression-tested with mips-sde-elf, fixing numerous failures like: (gdb) PASS: gdb.base/display.exp: display/s &sum cont Continuing. Program received signal SIGTRAP, Trace/breakpoint trap. 0x80001176 in do_loops () at .../gdb/testsuite/gdb.base/display.c:22 22 sum++; f++; force_mem (&k); 5: x/s &sum 0x80004cc0 : "" 4: /f f = 3.1415 3: x/i &k 0x80505b80: nop 2: /x j = 0x0 1: i = 0 (gdb) FAIL: gdb.base/display.exp: first disp which is now: (gdb) PASS: gdb.base/display.exp: display/s &sum cont Continuing. Hardware watchpoint 3: sum Old value = 0 New value = 1 0x80001176 in do_loops () at .../gdb/testsuite/gdb.base/display.c:22 22 sum++; f++; force_mem (&k); 5: x/s &sum 0x80004cc0 : "" 4: /f f = 3.1415 3: x/i &k 0x80505b80: nop 2: /x j = 0x0 1: i = 0 (gdb) PASS: gdb.base/display.exp: first disp and introducing no new ones. Tested for mips-linux-gnu successfully too; no improvement there as the issue with kernel-mode addresses does not apply to Linux userland. OK to apply? 2011-11-30 Maciej W. Rozycki gdb/ * remote.c (remote_watchpoint_addr_within_range): New function. (init_remote_ops): Use it. Maciej gdb-remote-watch-range.diff Index: gdb-fsf-trunk-quilt/gdb/remote.c =================================================================== --- gdb-fsf-trunk-quilt.orig/gdb/remote.c 2011-11-30 16:59:46.215590824 +0000 +++ gdb-fsf-trunk-quilt/gdb/remote.c 2011-11-30 17:01:56.045448615 +0000 @@ -7805,6 +7805,15 @@ remote_insert_watchpoint (CORE_ADDR addr _("remote_insert_watchpoint: reached end of function")); } +static int +remote_watchpoint_addr_within_range (struct target_ops *target, CORE_ADDR addr, + CORE_ADDR start, int length) +{ + CORE_ADDR diff = remote_address_masked (addr - start); + + return diff >= 0 && diff < length; +} + static int remote_remove_watchpoint (CORE_ADDR addr, int len, int type, @@ -10509,6 +10518,8 @@ Specify the serial device it is connecte remote_ops.to_remove_breakpoint = remote_remove_breakpoint; remote_ops.to_stopped_by_watchpoint = remote_stopped_by_watchpoint; remote_ops.to_stopped_data_address = remote_stopped_data_address; + remote_ops.to_watchpoint_addr_within_range = + remote_watchpoint_addr_within_range; remote_ops.to_can_use_hw_breakpoint = remote_check_watch_resources; remote_ops.to_insert_hw_breakpoint = remote_insert_hw_breakpoint; remote_ops.to_remove_hw_breakpoint = remote_remove_hw_breakpoint;