2009-06-27 Michael Snyder <msnyder@vmware.com>
[external/binutils.git] / gdb / testsuite / gdb.reverse / watch-reverse.c
1 /* This testcase is part of GDB, the GNU debugger.
2
3    Copyright 2008, 2009
4    Free Software Foundation, Inc.
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
18
19 #include <stdio.h>
20 #include <unistd.h>
21 /*
22  *      Since using watchpoints can be very slow, we have to take some pains to
23  *      ensure that we don't run too long with them enabled or we run the risk
24  *      of having the test timeout.  To help avoid this, we insert some marker
25  *      functions in the execution stream so we can set breakpoints at known
26  *      locations, without worrying about invalidating line numbers by changing
27  *      this file.  We use null bodied functions are markers since gdb does
28  *      not support breakpoints at labeled text points at this time.
29  *
30  *      One place we need is a marker for when we start executing our tests
31  *      instructions rather than any process startup code, so we insert one
32  *      right after entering main().  Another is right before we finish, before
33  *      we start executing any process termination code.
34  *
35  *      Another problem we have to guard against, at least for the test
36  *      suite, is that we need to ensure that the line that causes the
37  *      watchpoint to be hit is still the current line when gdb notices
38  *      the hit.  Depending upon the specific code generated by the compiler,
39  *      the instruction after the one that triggers the hit may be part of
40  *      the same line or part of the next line.  Thus we ensure that there
41  *      are always some instructions to execute on the same line after the
42  *      code that should trigger the hit.
43  */
44
45 int count = -1;
46 int ival1 = -1;
47 int ival2 = -1;
48 int ival3 = -1;
49 int ival4 = -1;
50 int ival5 = -1;
51 char buf[10];
52 struct foo
53 {
54   int val;
55 };
56 struct foo struct1, struct2, *ptr1, *ptr2;
57
58 int doread = 0;
59
60 char *global_ptr;
61
62 void marker1 ()
63 {
64 }
65
66 void marker2 ()
67 {
68 }
69
70 void marker4 ()
71 {
72 }
73
74 void marker5 ()
75 {
76 }
77
78 void marker6 ()
79 {
80 }
81
82 #ifdef PROTOTYPES
83 void recurser (int  x)
84 #else
85 void recurser (x) int  x;
86 #endif
87 {
88   int  local_x;
89
90   if (x > 0)
91     recurser (x-1);
92   local_x = x;
93 }
94
95 void
96 func2 ()
97 {
98   int  local_a;
99   static int  static_b;
100
101   ival5++;
102   local_a = ival5;
103   static_b = local_a;
104 }
105
106 void
107 func3 ()
108 {
109   int x;
110   int y;
111
112   x = 0;
113   x = 1;                                /* second x assignment */
114   y = 1;
115   y = 2;
116 }
117
118 int
119 func1 ()
120 {
121   /* The point of this is that we will set a breakpoint at this call.
122
123      Then, if DECR_PC_AFTER_BREAK equals the size of a function call
124      instruction (true on a sun3 if this is gcc-compiled--FIXME we
125      should use asm() to make it work for any compiler, present or
126      future), then we will end up branching to the location just after
127      the breakpoint.  And we better not confuse that with hitting the
128      breakpoint.  */
129   func2 ();
130   return 73;
131 }
132
133 void
134 func4 ()
135 {
136   buf[0] = 3;
137   global_ptr = buf;
138   buf[0] = 7;
139 }
140
141 int main ()
142 {
143 #ifdef usestubs
144   set_debug_traps();
145   breakpoint();
146 #endif
147   struct1.val = 1;
148   struct2.val = 2;
149   ptr1 = &struct1;
150   ptr2 = &struct2;
151   marker1 ();
152   func1 ();
153   for (count = 0; count < 4; count++) {
154     ival1 = count;
155     ival3 = count; ival4 = count;
156   }
157   ival1 = count; /* Outside loop */
158   ival2 = count;
159   ival3 = count; ival4 = count;
160   marker2 ();
161   if (doread)
162     {
163       static char msg[] = "type stuff for buf now:";
164       write (1, msg, sizeof (msg) - 1);
165       read (0, &buf[0], 5);
166     }
167   marker4 ();
168
169   /* We have a watchpoint on ptr1->val.  It should be triggered if
170      ptr1's value changes.  */
171   ptr1 = ptr2;
172
173   /* This should not trigger the watchpoint.  If it does, then we
174      used the wrong value chain to re-insert the watchpoints or we
175      are not evaluating the watchpoint expression correctly.  */
176   struct1.val = 5;
177   marker5 ();
178
179   /* We have a watchpoint on ptr1->val.  It should be triggered if
180      ptr1's value changes.  */
181   ptr1 = ptr2;
182
183   /* This should not trigger the watchpoint.  If it does, then we
184      used the wrong value chain to re-insert the watchpoints or we
185      are not evaluating the watchpoint expression correctly.  */
186   struct1.val = 5;
187   marker5 ();
188
189   /* We're going to watch locals of func2, to see that out-of-scope
190      watchpoints are detected and properly deleted.
191      */
192   marker6 ();
193
194   /* This invocation is used for watches of a single
195      local variable. */
196   func2 ();
197
198   /* This invocation is used for watches of an expression
199      involving a local variable. */
200   func2 ();
201
202   /* This invocation is used for watches of a static
203      (non-stack-based) local variable. */
204   func2 ();
205
206   /* This invocation is used for watches of a local variable
207      when recursion happens.
208      */
209   marker6 ();
210   recurser (2);
211
212   marker6 ();
213
214   func3 ();
215
216   func4 ();
217
218   return 0;
219 }