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