From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 18228 invoked by alias); 6 Dec 2010 11:14:20 -0000 Received: (qmail 18219 invoked by uid 22791); 6 Dec 2010 11:14:19 -0000 X-SWARE-Spam-Status: No, hits=-6.2 required=5.0 tests=AWL,BAYES_00,RCVD_IN_DNSWL_HI,SPF_HELO_PASS,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 06 Dec 2010 11:14:15 +0000 Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id oB6BEDGZ003624 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Mon, 6 Dec 2010 06:14:13 -0500 Received: from host0.dyn.jankratochvil.net (ovpn01.gateway.prod.ext.phx2.redhat.com [10.5.9.1]) by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id oB6BE83r018385 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Mon, 6 Dec 2010 06:14:12 -0500 Received: from host0.dyn.jankratochvil.net (host0.dyn.jankratochvil.net [127.0.0.1]) by host0.dyn.jankratochvil.net (8.14.4/8.14.4) with ESMTP id oB6BE7g9027828 for ; Mon, 6 Dec 2010 12:14:07 +0100 Received: (from jkratoch@localhost) by host0.dyn.jankratochvil.net (8.14.4/8.14.4/Submit) id oB6BE6in027821 for gdb-patches@sourceware.org; Mon, 6 Dec 2010 12:14:06 +0100 Date: Mon, 06 Dec 2010 11:14:00 -0000 From: Jan Kratochvil To: gdb-patches@sourceware.org Subject: [patch 3/4] hw watchpoints kernel workaround Message-ID: <20101206111405.GD27176@host0.dyn.jankratochvil.net> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) X-IsSubscribed: yes 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: 2010-12/txt/msg00044.txt.bz2 Hi, there has been a change in upstream Linux kernels behavior. Formerly newly created processes/threads inherited the debug registers content. Very recently the new processes/threads get the debug registers cleared. ptrace: watchpoint-fork (DR fork() inheritance) https://bugzilla.redhat.com/show_bug.cgi?id=660003 http://sources.redhat.com/cgi-bin/cvsweb.cgi/tests/ptrace-tests/tests/Attic/watchpoint-fork.c?rev=1.3&cvsroot=systemtap if $? == 0 then it is old-style kernel - debug registers get inherited if $? == 1 then it is new-style kernel - debug registers get zeroed In fact so far I do not know it would cause any problem. It rather workarounds a GDB bug described in [patch 2/4] (b). For threads GDB is already ensuring the right debug registers content: linux_nat_set_new_thread (t, amd64_linux_new_thread); But together with the second change in upstream Linux kernels behavior: ptrace: watchpoint-zeroaddr: EINVAL on PTRACE_POKEUSER of DR7 https://bugzilla.redhat.com/show_bug.cgi?id=660204 http://sources.redhat.com/cgi-bin/cvsweb.cgi/tests/ptrace-tests/tests/watchpoint-zeroaddr.c?rev=1.1&cvsroot=systemtap if $? == 0 then it is old-style kernel - anything is allowed if $? == 1 then it is new-style kernel - EINVAL given on invalid DRs state there is a problem GDB tries to remove watchpoints from registers where are already zeroes (due to the first kernel change/bug). And despite GDB "safely" tries to unset control register first and only then reset the address registers still for 2+ watchpoints it causes the kernel EINVAL. I tried to make GDB working with any combination of these two behavior changes present as such kernels are already released in the wild. Therefore here is the workaround. It is needed only on the new-style kernels. (scope: RHEL-6 is old-style, updated Fedora 13 is already new-style) BTW these are upstream Linux kernel behavior changes unrelated to utrace. I do not know exact kernel version/commit of the change(s). Thanks, Jan gdb/ 2010-12-06 Jan Kratochvil Workaround Linux kernel Bug - Red Hat Bugzilla #660204. * i386-nat.c (i386_remove_aligned_watchpoint): New variables inferior_pid and inf. pid != inferior_pid>: New. --- a/gdb/i386-nat.c +++ b/gdb/i386-nat.c @@ -453,6 +453,24 @@ i386_remove_aligned_watchpoint (CORE_ADDR addr, unsigned len_rw_bits) { struct dr_mirror *dr_mirror = dr_mirror_get (); int i, retval = -1; + int inferior_pid = ptid_get_pid (inferior_ptid); + struct inferior *inf = current_inferior (); + + /* Are we detaching breakpoints from a fork-ed child? + See linux_nat_iterate_watchpoint_lwps. */ + if (inf->pid != inferior_pid) + { + int i; + + /* Workaround some kernel versions reporting EINVAL on setting + DR_CONTROL with still unset (and thus zero) DR_*ADDR registers. + See: https://bugzilla.redhat.com/show_bug.cgi?id=660204 + It can happen as some kernel versions reset all DR registers to zero + for the fork-ed child; other kernels copy them from the parent. */ + + ALL_DEBUG_REGISTERS(i) + i386_dr_low.set_addr (i, dr_mirror->addr[i]); + } ALL_DEBUG_REGISTERS(i) {