X-Authentication-Warning: delorie.com: mail set sender to djgpp-workers-bounces using -f X-Recipient: djgpp-workers AT delorie DOT com From: "Pierre Muller" To: Cc: "'Eli Zaretskii'" Subject: Patch for windows watchpoint bug Date: Tue, 9 Jun 2009 17:06:21 +0200 Message-ID: <001501c9e913$d9751830$8c5f4890$@u-strasbg.fr> MIME-Version: 1.0 Content-Type: text/plain; charset="US-ASCII" Content-Transfer-Encoding: 7bit X-Mailer: Microsoft Office Outlook 12.0 Thread-Index: AcnpE9a1pGndGs1hQl+q1ab1Fu7D7A== Content-Language: en-us X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.0.1 (mailhost.u-strasbg.fr [IPv6:2001:660:2402::151]); Tue, 09 Jun 2009 17:06:19 +0200 (CEST) X-Virus-Scanned: ClamAV 0.94.2/9444/Tue Jun 9 15:59:19 2009 on mr1.u-strasbg.fr X-Virus-Status: Clean X-Spam-Status: No, score=-100.0 required=5.0 tests=USER_IN_WHITELIST autolearn=disabled version=3.2.5 X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on mr1.u-strasbg.fr Reply-To: djgpp-workers AT delorie DOT com Using more than one watchpoints doesn't work on my Windows XP Pro SP3. I found a way to fix this: my patch simply splits the _clear_break_DPMI into two parts, a first iteration over the four possibly used watchpoint handles to call __dpmi_get_state_of_debug_watchpoint followed by a second iteration to disable the watchpoints calling __dpmi_clear_debug_watchpoint. I suspect that the Windows DPMI server resets all watchpoint-hit bits as soon as a given watchpoint is disabled. disabling the watchpoints in a second iteration allows to avoid that bug. I don't think that other DPMI servers that don't have this bug should suffer from that code change. Can be simply tested by ./gdb ./gdb (gdb) set prompt top> /* To avoid the problem of watchpoint to hardware watchpoint promotion, start the debuggee first */ top> start ... top> watch gdb_stderr top> watch gdb_stdout top> cont And check that both watchpoints are correctly hit. (without my patch, I get a watchpoint hit on gdb_stdout, but a SIGTRAP due to dr6 being found equal to 0 for the gdb_stderr watchpoint). I also have a patch for v2.03, but I don't know if this is still useful. It might be for gdb 7.0 Pierre Muller Index: dbgcom.c =================================================================== RCS file: /cvs/djgpp/djgpp/src/debug/common/dbgcom.c,v retrieving revision 1.28 diff -u -p -r1.28 dbgcom.c --- dbgcom.c 9 Apr 2009 18:24:17 -0000 1.28 +++ dbgcom.c 9 Jun 2009 12:47:03 -0000 @@ -218,21 +218,27 @@ void load_npx (void) asm volatile ("frstor %0" : "=m" (npx)); } -static int _DPMIcancelBreak(int handle) +static int _DPMIhitBreak(int handle) { int rv, state; rv = __dpmi_get_state_of_debug_watchpoint(handle, &state); if(rv == -1) { printf("DPMI get watchpoint state failed for handle 0x%x\n",handle); - state = 0; + return -1; } + return (state & 1); +} + +static int _DPMIcancelBreak(int handle) +{ + int rv; + rv = __dpmi_clear_debug_watchpoint(handle); if(rv == -1) printf("DPMI release watchpoint failed for handle 0x%x\n",handle); - /* printf("CancelBreak han=0x%x returns state=0x%x\n",handle,state); */ - return (state & 1); + return (rv); } /* Can't be static because called in asm below; -O3 inlines if static */ @@ -277,7 +283,7 @@ void _set_break_DPMI(void) void _clear_break_DPMI(void); void _clear_break_DPMI(void) { - int i,bt; + int i,bt,res; if(!nset) { edi.dr[6] = 0; @@ -288,10 +294,20 @@ void _clear_break_DPMI(void) for(i=3;i>=0;i--) { bt = bt << 1; /* Shift for next bit */ if(breakhandle[i] != -1) - bt |= _DPMIcancelBreak(breakhandle[i]); /* Set low bit if active */ + { + res = _DPMIhitBreak(breakhandle[i]); /* Set low bit if active */ + if (res >=0) + bt |= res; + } } edi.dr[6] = bt; + for(i=3;i>=0;i--) { + bt = bt << 1; /* Shift for next bit */ + if(breakhandle[i] != -1) + bt |= _DPMIcancelBreak(breakhandle[i]); /* Set low bit if active */ + } + } static __dpmi_paddr old_i31,old_i21,user_i31,user_i21;