]>
Commit | Line | Data |
---|---|---|
3a58abaf AM |
1 | 2008-07-10 Jan Kratochvil <jan.kratochvil@redhat.com> |
2 | ||
3 | * breakpoint.c (fetch_watchpoint_value): New comment on unreachable | |
4 | values. | |
5 | (watch_command_1): New variable VAL_CHAIN. Refuse constant watchpoints. | |
6 | * gdbtypes.h (TYPE_CODE_FUNC): New comment regarding pointers to it. | |
7 | ||
8 | 2008-07-10 Jan Kratochvil <jan.kratochvil@redhat.com> | |
9 | ||
10 | * gdb.texinfo (Set Watchpoints): Document constant value watchpoints. | |
11 | ||
12 | 2008-07-10 Jan Kratochvil <jan.kratochvil@redhat.com> | |
13 | ||
14 | * gdb.base/watchpoint.exp: Call TEST_CONSTANT_WATCHPOINT. | |
15 | (test_constant_watchpoint): New function. | |
16 | (test_inaccessible_watchpoint): Cleanup (delete) the watchpoint. | |
17 | Test also a double-indirection watchpoint. | |
18 | gdb.base/watchpoint.c (global_ptr_ptr): New variable. | |
19 | (func4): New testing code for GLOBAL_PTR_PTR. | |
20 | ||
7566401a | 21 | Index: gdb-6.8.50.20090803/gdb/breakpoint.c |
3a58abaf | 22 | =================================================================== |
7566401a ER |
23 | --- gdb-6.8.50.20090803.orig/gdb/breakpoint.c 2009-08-04 06:29:47.000000000 +0200 |
24 | +++ gdb-6.8.50.20090803/gdb/breakpoint.c 2009-08-04 06:32:50.000000000 +0200 | |
25 | @@ -823,7 +823,15 @@ is_hardware_watchpoint (struct breakpoin | |
3a58abaf AM |
26 | If VAL_CHAIN is non-NULL, *VAL_CHAIN will be released from the |
27 | value chain. The caller must free the values individually. If | |
28 | VAL_CHAIN is NULL, all generated values will be left on the value | |
29 | - chain. */ | |
30 | + chain. | |
31 | + | |
32 | + Inferior unreachable values return: | |
33 | + Inferior `int *intp = NULL;' with `watch *intp': | |
34 | + *VALP is NULL, *RESULTP contains lazy LVAL_MEMORY address 0, *VAL_CHAIN | |
35 | + contains the *RESULTP element and also INTP as LVAL_MEMORY. | |
36 | + Inferior `int **intpp = NULL;' with `watch **intpp': | |
37 | + *VALP is NULL, *RESULTP is NULL, *VAL_CHAIN contains lazy LVAL_MEMORY | |
38 | + address 0 and also INTPP as LVAL_MEMORY. */ | |
39 | ||
40 | static void | |
41 | fetch_watchpoint_value (struct expression *exp, struct value **valp, | |
7566401a | 42 | @@ -6301,7 +6309,7 @@ watch_command_1 (char *arg, int accessfl |
3a58abaf AM |
43 | struct symtab_and_line sal; |
44 | struct expression *exp; | |
45 | struct block *exp_valid_block; | |
46 | - struct value *val, *mark; | |
47 | + struct value *val, *mark, *val_chain; | |
48 | struct frame_info *frame; | |
3a58abaf | 49 | char *exp_start = NULL; |
7566401a ER |
50 | char *exp_end = NULL; |
51 | @@ -6392,6 +6400,27 @@ watch_command_1 (char *arg, int accessfl | |
3a58abaf AM |
52 | exp_valid_block = innermost_block; |
53 | mark = value_mark (); | |
54 | fetch_watchpoint_value (exp, &val, NULL, NULL); | |
55 | + | |
56 | + /* VALUE_MARK gets us the same value as FETCH_WATCHPOINT_VALUE's VAL_CHAIN | |
57 | + parameter. Just this way we do not have to VALUE_FREE the chained VALUEs | |
58 | + ourselves. */ | |
59 | + for (val_chain = value_mark (); | |
60 | + val_chain != mark; | |
61 | + val_chain = value_next (val_chain)) | |
62 | + if ((VALUE_LVAL (val_chain) == lval_memory | |
63 | + && TYPE_CODE (value_type (val_chain)) != TYPE_CODE_FUNC) | |
64 | + || VALUE_LVAL (val_chain) == lval_register) | |
65 | + break; | |
66 | + if (val_chain == mark) | |
67 | + { | |
68 | + int len; | |
69 | + | |
70 | + len = exp_end - exp_start; | |
71 | + while (len > 0 && isspace (exp_start[len - 1])) | |
72 | + len--; | |
73 | + error (_("Cannot watch constant value %.*s."), len, exp_start); | |
74 | + } | |
75 | + /* Break the values chain only after its check above. */ | |
76 | if (val != NULL) | |
77 | release_value (val); | |
78 | ||
7566401a | 79 | Index: gdb-6.8.50.20090803/gdb/gdbtypes.h |
3a58abaf | 80 | =================================================================== |
7566401a ER |
81 | --- gdb-6.8.50.20090803.orig/gdb/gdbtypes.h 2009-08-04 06:31:58.000000000 +0200 |
82 | +++ gdb-6.8.50.20090803/gdb/gdbtypes.h 2009-08-04 06:32:50.000000000 +0200 | |
83 | @@ -71,7 +71,22 @@ enum type_code | |
3a58abaf AM |
84 | TYPE_CODE_UNION, /* C union or Pascal variant part */ |
85 | TYPE_CODE_ENUM, /* Enumeration type */ | |
86 | TYPE_CODE_FLAGS, /* Bit flags type */ | |
87 | - TYPE_CODE_FUNC, /* Function type */ | |
88 | + | |
89 | + /* Function type. It is not a pointer to a function. Function reference | |
90 | + by its name (such as `printf') has this type. C automatically converts | |
91 | + this function type to a pointer to function for any operation except | |
92 | + `sizeof (function_type)' or `&function_type' (unary &). | |
93 | + `sizeof (function_type)' is undefined in C. But GCC provides extension | |
94 | + (info '(gcc)Pointer Arith') defining its size as 1 byte. DWARF does not | |
95 | + define its size but GDB defines the size the GCC compatible way - GDB | |
96 | + function MAKE_FUNCTION_TYPE. The address itself is not modifiable. | |
97 | + As the function type has size 1 but its real value has `sizeof | |
98 | + (CORE_ADDR)' we cannot use NOT_LVAL category because the address would | |
99 | + not fit in the VALUE_CONTENTS_RAW container of its VALUE. We use | |
100 | + LVAL_MEMORY (and its VALUE_ADDRESS field) for it but we must be careful | |
101 | + it is not lvalue, it is the only non-modifiable LVAL_MEMORY. */ | |
102 | + TYPE_CODE_FUNC, | |
103 | + | |
104 | TYPE_CODE_INT, /* Integer type */ | |
105 | ||
106 | /* Floating type. This is *NOT* a complex type. Beware, there are parts | |
7566401a | 107 | Index: gdb-6.8.50.20090803/gdb/doc/gdb.texinfo |
3a58abaf | 108 | =================================================================== |
7566401a ER |
109 | --- gdb-6.8.50.20090803.orig/gdb/doc/gdb.texinfo 2009-08-04 06:32:39.000000000 +0200 |
110 | +++ gdb-6.8.50.20090803/gdb/doc/gdb.texinfo 2009-08-04 06:32:50.000000000 +0200 | |
111 | @@ -3517,6 +3517,18 @@ This command prints a list of watchpoint | |
3a58abaf AM |
112 | it is the same as @code{info break} (@pxref{Set Breaks}). |
113 | @end table | |
114 | ||
115 | +If you watch for a change in a numerically entered address you need to | |
116 | +dereference it as the address itself is just a constant number which will never | |
117 | +change. @value{GDBN} refuses to create a watchpoint that watches | |
118 | +a never-changing value: | |
119 | + | |
120 | +@smallexample | |
121 | +(@value{GDBP}) watch 0x600850 | |
122 | +Cannot watch constant value 0x600850. | |
123 | +(@value{GDBP}) watch *(int *) 0x600850 | |
124 | +Watchpoint 1: *(int *) 6293584 | |
125 | +@end smallexample | |
126 | + | |
127 | @value{GDBN} sets a @dfn{hardware watchpoint} if possible. Hardware | |
128 | watchpoints execute very quickly, and the debugger reports a change in | |
129 | value at the exact instruction where the change occurs. If @value{GDBN} | |
7566401a | 130 | Index: gdb-6.8.50.20090803/gdb/testsuite/gdb.base/watchpoint.c |
3a58abaf | 131 | =================================================================== |
7566401a ER |
132 | --- gdb-6.8.50.20090803.orig/gdb/testsuite/gdb.base/watchpoint.c 2008-03-03 14:24:12.000000000 +0100 |
133 | +++ gdb-6.8.50.20090803/gdb/testsuite/gdb.base/watchpoint.c 2009-08-04 06:32:50.000000000 +0200 | |
3a58abaf AM |
134 | @@ -40,6 +40,7 @@ struct foo struct1, struct2, *ptr1, *ptr |
135 | int doread = 0; | |
136 | ||
137 | char *global_ptr; | |
138 | +char **global_ptr_ptr; | |
139 | ||
140 | void marker1 () | |
141 | { | |
142 | @@ -118,6 +119,10 @@ func4 () | |
143 | buf[0] = 3; | |
144 | global_ptr = buf; | |
145 | buf[0] = 7; | |
146 | + buf[1] = 5; | |
147 | + global_ptr_ptr = &global_ptr; | |
148 | + buf[0] = 9; | |
149 | + global_ptr++; | |
150 | } | |
151 | ||
152 | int main () | |
7566401a | 153 | Index: gdb-6.8.50.20090803/gdb/testsuite/gdb.base/watchpoint.exp |
3a58abaf | 154 | =================================================================== |
7566401a ER |
155 | --- gdb-6.8.50.20090803.orig/gdb/testsuite/gdb.base/watchpoint.exp 2009-01-03 06:58:03.000000000 +0100 |
156 | +++ gdb-6.8.50.20090803/gdb/testsuite/gdb.base/watchpoint.exp 2009-08-04 06:32:50.000000000 +0200 | |
3a58abaf AM |
157 | @@ -641,7 +641,21 @@ proc test_watchpoint_and_breakpoint {} { |
158 | } | |
159 | } | |
160 | } | |
161 | - | |
162 | + | |
163 | +proc test_constant_watchpoint {} { | |
164 | + global gdb_prompt | |
165 | + | |
166 | + gdb_test "watch 5" "Cannot watch constant value 5." "number is constant" | |
167 | + gdb_test "watch marker1" "Cannot watch constant value marker1." \ | |
168 | + "marker1 is constant" | |
169 | + gdb_test "watch count + 6" ".*atchpoint \[0-9\]+: count \\+ 6" | |
170 | + gdb_test "set \$expr_breakpoint_number = \$bpnum" "" | |
171 | + gdb_test "delete \$expr_breakpoint_number" "" | |
172 | + gdb_test "watch 7 + count" ".*atchpoint \[0-9\]+: 7 \\+ count" | |
173 | + gdb_test "set \$expr_breakpoint_number = \$bpnum" "" | |
174 | + gdb_test "delete \$expr_breakpoint_number" "" | |
175 | +} | |
176 | + | |
177 | proc test_inaccessible_watchpoint {} { | |
178 | global gdb_prompt | |
179 | ||
180 | @@ -662,7 +676,8 @@ proc test_inaccessible_watchpoint {} { | |
181 | } | |
182 | ||
183 | gdb_test "watch *global_ptr" ".*atchpoint \[0-9\]+: \\*global_ptr" | |
184 | - gdb_test "next" ".*global_ptr = buf.*" | |
185 | + gdb_test "set \$global_ptr_breakpoint_number = \$bpnum" "" | |
186 | + gdb_test "next" ".*global_ptr = buf.*" "global_ptr next" | |
187 | gdb_test_multiple "next" "next over ptr init" { | |
188 | -re ".*atchpoint \[0-9\]+: \\*global_ptr\r\n\r\nOld value = .*\r\nNew value = 3 .*\r\n.*$gdb_prompt $" { | |
189 | # We can not test for <unknown> here because NULL may be readable. | |
190 | @@ -675,6 +690,28 @@ proc test_inaccessible_watchpoint {} { | |
191 | pass "next over buffer set" | |
192 | } | |
193 | } | |
194 | + gdb_test "delete \$global_ptr_breakpoint_number" "" | |
195 | + gdb_test "watch **global_ptr_ptr" ".*atchpoint \[0-9\]+: \\*\\*global_ptr_ptr" | |
196 | + gdb_test "set \$global_ptr_ptr_breakpoint_number = \$bpnum" "" | |
197 | + gdb_test "next" ".*global_ptr_ptr = &global_ptr.*" "gloabl_ptr_ptr next" | |
198 | + gdb_test_multiple "next" "next over global_ptr_ptr init" { | |
199 | + -re ".*atchpoint \[0-9\]+: \\*\\*global_ptr_ptr\r\n\r\nOld value = .*\r\nNew value = 7 .*\r\n.*$gdb_prompt $" { | |
200 | + # We can not test for <unknown> here because NULL may be readable. | |
201 | + # This test does rely on *NULL != 7. | |
202 | + pass "next over global_ptr_ptr init" | |
203 | + } | |
204 | + } | |
205 | + gdb_test_multiple "next" "next over global_ptr_ptr buffer set" { | |
206 | + -re ".*atchpoint \[0-9\]+: \\*\\*global_ptr_ptr\r\n\r\nOld value = 7 .*\r\nNew value = 9 .*\r\n.*$gdb_prompt $" { | |
207 | + pass "next over global_ptr_ptr buffer set" | |
208 | + } | |
209 | + } | |
210 | + gdb_test_multiple "next" "next over global_ptr_ptr pointer advance" { | |
211 | + -re ".*atchpoint \[0-9\]+: \\*\\*global_ptr_ptr\r\n\r\nOld value = 9 .*\r\nNew value = 5 .*\r\n.*$gdb_prompt $" { | |
212 | + pass "next over global_ptr_ptr pointer advance" | |
213 | + } | |
214 | + } | |
215 | + gdb_test "delete \$global_ptr_ptr_breakpoint_number" "" | |
216 | } | |
217 | } | |
218 | ||
219 | @@ -842,6 +879,17 @@ if [initialize] then { | |
220 | } | |
221 | ||
222 | test_watchpoint_and_breakpoint | |
223 | + | |
224 | + # See above. | |
225 | + if [istarget "mips-idt-*"] then { | |
226 | + gdb_exit | |
227 | + gdb_start | |
228 | + gdb_reinitialize_dir $srcdir/$subdir | |
229 | + gdb_load $binfile | |
230 | + initialize | |
231 | + } | |
232 | + | |
233 | + test_constant_watchpoint | |
234 | } | |
235 | ||
236 | # Restore old timeout |