From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 31841 invoked by alias); 11 Jun 2004 21:33:38 -0000 Mailing-List: contact gdb-patches-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sources.redhat.com Received: (qmail 31822 invoked from network); 11 Jun 2004 21:33:37 -0000 Received: from unknown (HELO mx1.redhat.com) (66.187.233.31) by sourceware.org with SMTP; 11 Jun 2004 21:33:37 -0000 Received: from int-mx1.corp.redhat.com (int-mx1.corp.redhat.com [172.16.52.254]) by mx1.redhat.com (8.12.10/8.12.10) with ESMTP id i5BLXZi5006413 for ; Fri, 11 Jun 2004 17:33:35 -0400 Received: from pobox.toronto.redhat.com (pobox.toronto.redhat.com [172.16.14.4]) by int-mx1.corp.redhat.com (8.11.6/8.11.6) with ESMTP id i5BLXY030004 for ; Fri, 11 Jun 2004 17:33:34 -0400 Received: from touchme.toronto.redhat.com (IDENT:postfix@touchme.toronto.redhat.com [172.16.14.9]) by pobox.toronto.redhat.com (8.12.8/8.12.8) with ESMTP id i5BLXYtn001191 for ; Fri, 11 Jun 2004 17:33:34 -0400 Received: from redhat.com (toocool.toronto.redhat.com [172.16.14.72]) by touchme.toronto.redhat.com (Postfix) with ESMTP id 6468D80019B for ; Fri, 11 Jun 2004 17:33:34 -0400 (EDT) Message-ID: <40CA252E.8050109@redhat.com> Date: Fri, 11 Jun 2004 21:33:00 -0000 From: Jeff Johnston User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20030624 Netscape/7.1 MIME-Version: 1.0 To: gdb-patches@sources.redhat.com Subject: [RFC]: x86 threaded watchpoint support [2/3] Content-Type: multipart/mixed; boundary="------------060609020309080207050906" X-SW-Source: 2004-06/txt/msg00280.txt.bz2 This is a multi-part message in MIME format. --------------060609020309080207050906 Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit Content-length: 1229 This is the 2nd part of getting x86 threaded watchpoints to work. It involves some fixes to breakpoint.c. The most major change is that a check has been added for a hardware_watchpoint to ensure that the stopped data address matches the watchpoint address. I do not know if there are platforms that have hardware_watchpoints but cannot tell what the data address is. If this problem exists, I can easily add a flag to determine if the stopped address can be used or not. Alternatively, the default stopped_data_address for such a platform could return a special value that the comparison check could treat as "don't know". Comments? Ok? -- Jeff J. 2004-06-11 Jeff Johnston * breakpoint.c (print_it_typical): Do not issue a warning message if we find a bp_thread_event and there are other items on the stop list. (bpstat_stop_status): When dealing with a hardware_watchpoint, check if the stopped data address matches the watched address for the current breakpoint in the list. When dealing with a read or access watchpoint, if the address does not match, remember to turn off the print for the newly added bpstat. --------------060609020309080207050906 Content-Type: text/plain; name="x86-watchpoint.patch2" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="x86-watchpoint.patch2" Content-length: 5430 Index: breakpoint.c =================================================================== RCS file: /cvs/src/src/gdb/breakpoint.c,v retrieving revision 1.174 diff -u -p -r1.174 breakpoint.c --- breakpoint.c 7 Jun 2004 17:58:32 -0000 1.174 +++ breakpoint.c 11 Jun 2004 21:22:42 -0000 @@ -2120,8 +2120,13 @@ print_it_typical (bpstat bs) break; case bp_thread_event: - /* Not sure how we will get here. - GDB should not stop for these breakpoints. */ + /* We can only get here legitimately if something further on the bs + list has caused the stop status to be noisy. A valid example + of this is a new thread event and a software watchpoint have + both occurred. */ + if (bs->next) + return PRINT_UNKNOWN; + printf_filtered ("Thread Event Breakpoint: gdb should not stop!\n"); return PRINT_NOTHING; break; @@ -2683,45 +2688,100 @@ bpstat_stop_status (CORE_ADDR bp_addr, p if (b->type == bp_watchpoint || b->type == bp_hardware_watchpoint) { - char *message = xstrprintf ("Error evaluating expression for watchpoint %d\n", + CORE_ADDR addr; + struct value *v; + int found = 0; + + /* If we have a hardware watchpoint, ensure that the address + being watched caused the trap event. */ + if (b->type == bp_hardware_watchpoint) + { + addr = target_stopped_data_address (); + if (addr == 0) + { + /* Don't stop. */ + bs->print_it = print_it_noop; + bs->stop = 0; + continue; + } + for (v = b->val_chain; v; v = v->next) + { + if (VALUE_LVAL (v) == lval_memory + && ! VALUE_LAZY (v)) + { + struct type *vtype = check_typedef (VALUE_TYPE (v)); + + if (v == b->val_chain + || (TYPE_CODE (vtype) != TYPE_CODE_STRUCT + && TYPE_CODE (vtype) != TYPE_CODE_ARRAY)) + { + CORE_ADDR vaddr; + + vaddr = VALUE_ADDRESS (v) + VALUE_OFFSET (v); + /* Exact match not required. Within range is + sufficient. */ + if (addr >= vaddr && + addr < vaddr + TYPE_LENGTH (VALUE_TYPE (v))) + found = 1; + } + } + } + } + else /* For a non-hardware watchpoint we need to test values. */ + found = 1; + + if (found) + { + char *message = xstrprintf ("Error evaluating expression for watchpoint %d\n", b->number); - struct cleanup *cleanups = make_cleanup (xfree, message); - int e = catch_errors (watchpoint_check, bs, message, - RETURN_MASK_ALL); - do_cleanups (cleanups); - switch (e) + struct cleanup *cleanups = make_cleanup (xfree, message); + int e = catch_errors (watchpoint_check, bs, message, + RETURN_MASK_ALL); + do_cleanups (cleanups); + switch (e) + { + case WP_DELETED: + /* We've already printed what needs to be printed. */ + /* Actually this is superfluous, because by the time we + call print_it_typical() the wp will be already deleted, + and the function will return immediately. */ + bs->print_it = print_it_done; + /* Stop. */ + break; + case WP_VALUE_CHANGED: + /* Stop. */ + ++(b->hit_count); + break; + case WP_VALUE_NOT_CHANGED: + /* Don't stop. */ + bs->print_it = print_it_noop; + bs->stop = 0; + continue; + default: + /* Can't happen. */ + /* FALLTHROUGH */ + case 0: + /* Error from catch_errors. */ + printf_filtered ("Watchpoint %d deleted.\n", b->number); + if (b->related_breakpoint) + b->related_breakpoint->disposition = disp_del_at_next_stop; + b->disposition = disp_del_at_next_stop; + /* We've already printed what needs to be printed. */ + bs->print_it = print_it_done; + + /* Stop. */ + break; + } + } + else /* found == 0 */ { - case WP_DELETED: - /* We've already printed what needs to be printed. */ - /* Actually this is superfluous, because by the time we - call print_it_typical() the wp will be already deleted, - and the function will return immediately. */ - bs->print_it = print_it_done; - /* Stop. */ - break; - case WP_VALUE_CHANGED: - /* Stop. */ - ++(b->hit_count); - break; - case WP_VALUE_NOT_CHANGED: - /* Don't stop. */ + /* This is a case where some watchpoint(s) triggered, + but not at the address of this watchpoint (FOUND + was left zero). So don't print anything for this + watchpoint. */ bs->print_it = print_it_noop; bs->stop = 0; - continue; - default: - /* Can't happen. */ - /* FALLTHROUGH */ - case 0: - /* Error from catch_errors. */ - printf_filtered ("Watchpoint %d deleted.\n", b->number); - if (b->related_breakpoint) - b->related_breakpoint->disposition = disp_del_at_next_stop; - b->disposition = disp_del_at_next_stop; - /* We've already printed what needs to be printed. */ - bs->print_it = print_it_done; - - /* Stop. */ - break; + continue; } } else if (b->type == bp_read_watchpoint || @@ -2733,7 +2793,12 @@ bpstat_stop_status (CORE_ADDR bp_addr, p addr = target_stopped_data_address (); if (addr == 0) - continue; + { + /* Don't stop. */ + bs->print_it = print_it_noop; + bs->stop = 0; + continue; + } for (v = b->val_chain; v; v = v->next) { if (VALUE_LVAL (v) == lval_memory --------------060609020309080207050906--