This is the mail archive of the gdb@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: When do watchpoints go out of scope?



Daniel Jacobowitz wrote:


On Sun, Sep 25, 2005 at 07:37:34AM -0700, Thomas Covenant wrote:


Consider this program:

1 int main(void)
2 {
3    {
4       int i = 2;
5       printf("i is %d.\n", i);
6       i = 3;
7       printf("i is %d.\n", i);
8    }
9    // lots more code
    ...
90   return 0;
100 }

The variable i goes in scope at line 4, out of scope
at line 8.

If I set:

watch i

at line 4, I would assume the watchpoint would be
deleted at line 8, since i is no longer in scope.


This depends on your compiler and the debug information it generates. If GDB still has location information, it will continue to watch the
variable. If it doesn't, it will stop. You didn't say what your
platform or compiler was, so it's hard to guess, but many older
versions of GCC and most targets using the stabs format do not have
accurate endings for lifetimes.





I'm a few weeks behind on my reading of this list, but...


There is a bug. I fixed it recently in our Xtensa port which is still
based on GDB 5.2.1. The problem is bpstat_stop_status() fails to delete
the watchpoint when it's scope breakpoint is hit (it gets deleted when
the program stops for some other reason). In fact it simply forgets
to handle the case of a watchpoint scope breakpoint. If you disable
the watchpoint and run till it's out of scope, it never gets deleted.

A cursory look at the GDB 6.3 source suggests it's still that way.

Here's my quick-fix to 5.2.1 (breakpoint.c, added lines marked with +):

------------------------------------------------------------------------

bpstat
bpstat_stop_status (CORE_ADDR *pc, int not_a_breakpoint)
{
  register struct breakpoint *b, *temp;
  CORE_ADDR bp_addr;
  /* True if we've hit a breakpoint (as opposed to a watchpoint).  */
  int real_breakpoint = 0;
  /* Root of the chain of bpstat's */
  struct bpstats root_bs[1];
  /* Pointer to the last thing in the chain currently.  */
  bpstat bs = root_bs;
  static char message1[] =
  "Error evaluating expression for watchpoint %d\n";
  char message[sizeof (message1) + 30 /* slop */ ];

  /* Get the address where the breakpoint would have been.
     The "not_a_breakpoint" argument is meant to distinguish
     between a breakpoint trap event and a trace/singlestep
     trap event.  For a trace/singlestep trap event, we would
     not want to subtract DECR_PC_AFTER_BREAK from the PC. */

  bp_addr = *pc - (not_a_breakpoint && !SOFTWARE_SINGLE_STEP_P () ?
                   0 : DECR_PC_AFTER_BREAK);

  ALL_BREAKPOINTS_SAFE (b, temp)
  {
    if (b->enable_state == bp_disabled
    || b->enable_state == bp_shlib_disabled
    || b->enable_state == bp_call_disabled)
      continue;

+ /* If we hit a watchpoint scope breakpoint, find the associated watchpoint
+ and check it's scope (call watchpoint_check) and delete if out of scope.
+ TODO: Use related_breakpoint field of scope breakpoint to reference wp. */
+ if (b->type == bp_watchpoint_scope && b->address == bp_addr)
+ {
+ register struct breakpoint *b1, *temp1;
+ struct bpstats bs1tmp;
+ bpstat bs1 = &bs1tmp;
+ struct value *saved_val;
+
+ ALL_BREAKPOINTS_SAFE (b1, temp1)
+ {
+ if (b1->related_breakpoint != b)
+ continue;
+
+ saved_val = b1->val;
+ bs1->breakpoint_at = b1;
+ sprintf (message, message1, b1->number);
+ catch_errors (watchpoint_check, bs1, message, RETURN_MASK_ALL);
+ /* The deed is done - we don't care about the result. */
+
+ /* Restore value & disposition in case changed by watchpoint_check(). */
+ b1->val = saved_val;
+ }
+ }
+
if (b->type != bp_watchpoint
&& b->type != bp_hardware_watchpoint
&& b->type != bp_read_watchpoint
&& b->type != bp_access_watchpoint
&& b->type != bp_hardware_breakpoint
&& b->type != bp_catch_fork
&& b->type != bp_catch_vfork
&& b->type != bp_catch_exec
&& b->type != bp_catch_catch
&& b->type != bp_catch_throw) /* a non-watchpoint bp */
{
if (b->address != bp_addr) /* address doesn't match */
continue;
if (overlay_debugging /* unmapped overlay section */
&& section_is_overlay (b->section)
&& !section_is_mapped (b->section))
continue;
}
------------------------------------------------------------------------


I can't submit this to the source base because we're not yet up to date.
Anyone can feel free to apply this to the top of trunk and improve on it.

Ross Morley
Tensilica, Inc.





Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]