diff options
Diffstat (limited to 'gdb/testsuite/gdb.hp/watch-hp.c')
-rw-r--r-- | gdb/testsuite/gdb.hp/watch-hp.c | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/gdb/testsuite/gdb.hp/watch-hp.c b/gdb/testsuite/gdb.hp/watch-hp.c new file mode 100644 index 00000000000..7336fe2bec8 --- /dev/null +++ b/gdb/testsuite/gdb.hp/watch-hp.c @@ -0,0 +1,166 @@ +#include <stdio.h> +/* + * Since using watchpoints can be very slow, we have to take some pains to + * ensure that we don't run too long with them enabled or we run the risk + * of having the test timeout. To help avoid this, we insert some marker + * functions in the execution stream so we can set breakpoints at known + * locations, without worrying about invalidating line numbers by changing + * this file. We use null bodied functions are markers since gdb does + * not support breakpoints at labeled text points at this time. + * + * One place we need is a marker for when we start executing our tests + * instructions rather than any process startup code, so we insert one + * right after entering main(). Another is right before we finish, before + * we start executing any process termination code. + * + * Another problem we have to guard against, at least for the test + * suite, is that we need to ensure that the line that causes the + * watchpoint to be hit is still the current line when gdb notices + * the hit. Depending upon the specific code generated by the compiler, + * the instruction after the one that triggers the hit may be part of + * the same line or part of the next line. Thus we ensure that there + * are always some instructions to execute on the same line after the + * code that should trigger the hit. + */ + +int count = -1; +int ival1 = -1; +int ival2 = -1; +int ival3 = -1; +int ival4 = -1; +int ival5 = -1; +char buf[10]; +struct foo +{ + int val; +}; +struct foo struct1, struct2, *ptr1, *ptr2; + +int doread = 0; + +void marker1 () +{ +} + +void marker2 () +{ +} + +void marker4 () +{ +} + +void marker5 () +{ +} + +void marker6 () +{ +} + +void recurser (x) + int x; +{ + int local_x; + + if (x > 0) + recurser (x-1); + local_x = x; +} + +void +func2 () +{ + int local_a; + static int static_b; + + ival5++; + local_a = ival5; + static_b = local_a; +} + +int +func1 () +{ + /* The point of this is that we will set a breakpoint at this call. + + Then, if DECR_PC_AFTER_BREAK equals the size of a function call + instruction (true on a sun3 if this is gcc-compiled--FIXME we + should use asm() to make it work for any compiler, present or + future), then we will end up branching to the location just after + the breakpoint. And we better not confuse that with hitting the + breakpoint. */ + func2 (); + return 73; +} + +int main () +{ + struct1.val = 1; + struct2.val = 2; + ptr1 = &struct1; + ptr2 = &struct2; + marker1 (); + func1 (); + for (count = 0; count < 4; count++) { + ival1 = count; + ival3 = count; ival4 = count; + } + ival1 = count; /* Outside loop */ + ival2 = count; + ival3 = count; ival4 = count; + marker2 (); + if (doread) + { + static char msg[] = "type stuff for buf now:"; + write (1, msg, sizeof (msg) - 1); + read (0, &buf[0], 5); + } + marker4 (); + + /* We have a watchpoint on ptr1->val. It should be triggered if + ptr1's value changes. */ + ptr1 = ptr2; + + /* This should not trigger the watchpoint. If it does, then we + used the wrong value chain to re-insert the watchpoints or we + are not evaluating the watchpoint expression correctly. */ + struct1.val = 5; + marker5 (); + + /* We have a watchpoint on ptr1->val. It should be triggered if + ptr1's value changes. */ + ptr1 = ptr2; + + /* This should not trigger the watchpoint. If it does, then we + used the wrong value chain to re-insert the watchpoints or we + are not evaluating the watchpoint expression correctly. */ + struct1.val = 5; + marker5 (); + + /* We're going to watch locals of func2, to see that out-of-scope + watchpoints are detected and properly deleted. + */ + marker6 (); + + /* This invocation is used for watches of a single + local variable. */ + func2 (); + + /* This invocation is used for watches of an expression + involving a local variable. */ + func2 (); + + /* This invocation is used for watches of a static + (non-stack-based) local variable. */ + func2 (); + + /* This invocation is used for watches of a local variable + when recursion happens. + */ + marker6 (); + recurser (2); + + marker6 (); + return 0; +} |