]>
Commit | Line | Data |
---|---|---|
3a58abaf AM |
1 | http://sourceware.org/ml/gdb-patches/2008-01/msg00042.html |
2 | [ Backported for GDB-6.6 (only removed the new file inclusion). ] | |
3 | ||
4 | + | |
5 | ||
6 | 2007-09-16 Daniel Jacobowitz <dan@codesourcery.com> | |
7 | Jeff Johnston <jjohnstn@redhat.com> | |
8 | ||
9 | * gdb.texinfo (Setting Watchpoints): Adjust warning text about | |
10 | multi-threaded watchpoints. | |
11 | ||
12 | 2007-12-15 Jan Kratochvil <jan.kratochvil@redhat.com> | |
13 | ||
14 | * gdb.texinfo (Setting Watchpoints): New paragraph on the software | |
15 | watchpoints safety wrt `set scheduler-locking'. | |
16 | ||
17 | 2008-03-01 Jan Kratochvil <jan.kratochvil@redhat.com> | |
18 | ||
19 | Port to GDB-6.8pre. | |
20 | ||
21 | 2008-03-31 Jan Kratochvil <jan.kratochvil@redhat.com> | |
22 | ||
23 | * gdb.threads/watchpoint-fork-forkoff.c (forkoff): New delay after the | |
24 | parent/child messages to fix a race. | |
25 | ||
26 | 2008-05-28 Jan Kratochvil <jan.kratochvil@redhat.com> | |
27 | ||
28 | * s390-nat.c (s390_fix_watch_points): Fix its compilation failure | |
29 | - rename it to S390_FIX_WATCH_POINTS_LIST. | |
30 | ||
31 | Index: gdb-6.8.50.20090209/gdb/amd64-linux-nat.c | |
32 | =================================================================== | |
33 | --- gdb-6.8.50.20090209.orig/gdb/amd64-linux-nat.c 2009-02-09 16:02:27.000000000 +0100 | |
34 | +++ gdb-6.8.50.20090209/gdb/amd64-linux-nat.c 2009-02-09 16:03:30.000000000 +0100 | |
35 | @@ -408,25 +408,43 @@ amd64_linux_dr_set (ptid_t ptid, int reg | |
36 | void | |
37 | amd64_linux_dr_set_control (unsigned long control) | |
38 | { | |
39 | - struct lwp_info *lp; | |
40 | - ptid_t ptid; | |
41 | - | |
42 | amd64_linux_dr[DR_CONTROL] = control; | |
43 | - ALL_LWPS (lp, ptid) | |
44 | - amd64_linux_dr_set (ptid, DR_CONTROL, control); | |
45 | + | |
46 | + /* I386_DETACH_BREAKPOINTS may need to reset the registers on single process | |
47 | + not listed for ALL_LWPS. */ | |
48 | + | |
49 | + if (ptid_get_lwp (inferior_ptid) == 0) | |
50 | + amd64_linux_dr_set (inferior_ptid, DR_CONTROL, control); | |
51 | + else | |
52 | + { | |
53 | + struct lwp_info *lp; | |
54 | + ptid_t ptid; | |
55 | + | |
56 | + ALL_LWPS (lp, ptid) | |
57 | + amd64_linux_dr_set (ptid, DR_CONTROL, control); | |
58 | + } | |
59 | } | |
60 | ||
61 | void | |
62 | amd64_linux_dr_set_addr (int regnum, CORE_ADDR addr) | |
63 | { | |
64 | - struct lwp_info *lp; | |
65 | - ptid_t ptid; | |
66 | - | |
67 | gdb_assert (regnum >= 0 && regnum <= DR_LASTADDR - DR_FIRSTADDR); | |
68 | ||
69 | amd64_linux_dr[DR_FIRSTADDR + regnum] = addr; | |
70 | - ALL_LWPS (lp, ptid) | |
71 | - amd64_linux_dr_set (ptid, DR_FIRSTADDR + regnum, addr); | |
72 | + | |
73 | + /* I386_DETACH_BREAKPOINTS may need to reset the registers on single process | |
74 | + not listed for ALL_LWPS. */ | |
75 | + | |
76 | + if (ptid_get_lwp (inferior_ptid) == 0) | |
77 | + amd64_linux_dr_set (inferior_ptid, DR_FIRSTADDR + regnum, addr); | |
78 | + else | |
79 | + { | |
80 | + struct lwp_info *lp; | |
81 | + ptid_t ptid; | |
82 | + | |
83 | + ALL_LWPS (lp, ptid) | |
84 | + amd64_linux_dr_set (ptid, DR_FIRSTADDR + regnum, addr); | |
85 | + } | |
86 | } | |
87 | ||
88 | void | |
89 | @@ -451,6 +469,41 @@ amd64_linux_new_thread (ptid_t ptid) | |
90 | ||
91 | amd64_linux_dr_set (ptid, DR_CONTROL, amd64_linux_dr[DR_CONTROL]); | |
92 | } | |
93 | + | |
94 | +/* TO_FOLLOW_FORK stores here the PID under DETACH_BREAKPOINTS for the child | |
95 | + process of traced FORK. We must clear such watchpoints only once during | |
96 | + DETACH_BREAKPOINTS. */ | |
97 | + | |
98 | +static int amd64_linux_detach_breakpoints_pid; | |
99 | + | |
100 | +/* Remove a watchpoint that watched the memory region which starts at | |
101 | + address ADDR, whose length is LEN bytes, and for accesses of the | |
102 | + type TYPE. Return 0 on success, -1 on failure. */ | |
103 | +int | |
104 | +amd64_linux_remove_watchpoint (CORE_ADDR addr, int len, int type) | |
105 | +{ | |
106 | + if (ptid_get_pid (inferior_ptid) == amd64_linux_detach_breakpoints_pid) | |
107 | + return 0; | |
108 | + /* FOLLOW-FORK-MODE CHILD runs later the CHILD with no restrictions. */ | |
109 | + amd64_linux_detach_breakpoints_pid = 0; | |
110 | + | |
111 | + return i386_remove_watchpoint (addr, len, type); | |
112 | +} | |
113 | + | |
114 | +static void | |
115 | +amd64_linux_detach_breakpoints (int detached_pid) | |
116 | +{ | |
117 | + struct cleanup *old_chain = save_inferior_ptid (); | |
118 | + int i; | |
119 | + | |
120 | + amd64_linux_detach_breakpoints_pid = detached_pid; | |
121 | + /* Depend on `!is_lwp (inferior_ptid)' for the I386_* macros. */ | |
122 | + inferior_ptid = pid_to_ptid (detached_pid); | |
123 | + | |
124 | + i386_detach_breakpoints (detached_pid); | |
125 | + | |
126 | + do_cleanups (old_chain); | |
127 | +} | |
128 | \f | |
129 | ||
130 | /* This function is called by libthread_db as part of its handling of | |
131 | @@ -755,6 +808,42 @@ amd64_linux_siginfo_fixup (struct siginf | |
132 | return 0; | |
133 | } | |
134 | ||
135 | +static int (*amd64_linux_super_follow_fork) (struct target_ops *ops, | |
136 | + int follow_child); | |
137 | + | |
138 | +/* We need to duplicate the LINUX_CHILD_FOLLOW_FORK behavior here and catch its | |
139 | + called DETACH_BREAKPOINTS to avoid corrupting our local registers mirror. */ | |
140 | + | |
141 | +static int | |
142 | +amd64_linux_follow_fork (struct target_ops *ops, int follow_child) | |
143 | +{ | |
144 | + ptid_t last_ptid; | |
145 | + struct target_waitstatus last_status; | |
146 | + int has_vforked; | |
147 | + int parent_pid, child_pid; | |
148 | + | |
149 | + get_last_target_status (&last_ptid, &last_status); | |
150 | + has_vforked = (last_status.kind == TARGET_WAITKIND_VFORKED); | |
151 | + parent_pid = ptid_get_lwp (last_ptid); | |
152 | + if (parent_pid == 0) | |
153 | + parent_pid = ptid_get_pid (last_ptid); | |
154 | + child_pid = ptid_get_lwp (last_status.value.related_pid); | |
155 | + if (child_pid == 0) | |
156 | + child_pid = ptid_get_pid (last_status.value.related_pid); | |
157 | + | |
158 | + if (! follow_child) | |
159 | + { | |
160 | + amd64_linux_detach_breakpoints (child_pid); | |
161 | + } | |
162 | + else | |
163 | + { | |
164 | + if (! has_vforked) | |
165 | + amd64_linux_detach_breakpoints (child_pid); | |
166 | + } | |
167 | + | |
168 | + return (*amd64_linux_super_follow_fork) (ops, follow_child); | |
169 | +} | |
170 | + | |
171 | /* Provide a prototype to silence -Wmissing-prototypes. */ | |
172 | void _initialize_amd64_linux_nat (void); | |
173 | ||
174 | @@ -791,6 +880,9 @@ _initialize_amd64_linux_nat (void) | |
175 | linux_elfcore_write_prstatus = amd64_linux_elfcore_write_prstatus; | |
176 | linux_elfcore_write_prfpreg = amd64_linux_elfcore_write_prfpreg; | |
177 | ||
178 | + amd64_linux_super_follow_fork = t->to_follow_fork; | |
179 | + t->to_follow_fork = amd64_linux_follow_fork; | |
180 | + | |
181 | /* Register the target. */ | |
182 | linux_nat_add_target (t); | |
183 | linux_nat_set_new_thread (t, amd64_linux_new_thread); | |
184 | Index: gdb-6.8.50.20090209/gdb/config/i386/nm-i386.h | |
185 | =================================================================== | |
186 | --- gdb-6.8.50.20090209.orig/gdb/config/i386/nm-i386.h 2009-01-03 06:57:54.000000000 +0100 | |
187 | +++ gdb-6.8.50.20090209/gdb/config/i386/nm-i386.h 2009-02-09 16:02:42.000000000 +0100 | |
188 | @@ -120,6 +120,8 @@ extern int i386_stopped_by_watchpoint (v | |
189 | ||
190 | #endif /* I386_WATCHPOINTS_IN_TARGET_VECTOR */ | |
191 | ||
192 | +extern void i386_detach_breakpoints (int detached_pid); | |
193 | + | |
194 | #endif /* I386_USE_GENERIC_WATCHPOINTS */ | |
195 | ||
196 | #endif /* NM_I386_H */ | |
197 | Index: gdb-6.8.50.20090209/gdb/i386-linux-nat.c | |
198 | =================================================================== | |
199 | --- gdb-6.8.50.20090209.orig/gdb/i386-linux-nat.c 2009-01-03 06:57:51.000000000 +0100 | |
200 | +++ gdb-6.8.50.20090209/gdb/i386-linux-nat.c 2009-02-09 16:02:42.000000000 +0100 | |
201 | @@ -634,21 +634,42 @@ i386_linux_dr_set_control (unsigned long | |
202 | ptid_t ptid; | |
203 | ||
204 | i386_linux_dr[DR_CONTROL] = control; | |
205 | - ALL_LWPS (lp, ptid) | |
206 | - i386_linux_dr_set (ptid, DR_CONTROL, control); | |
207 | + | |
208 | + /* I386_DETACH_BREAKPOINTS may need to reset the registers on single process | |
209 | + not listed for ALL_LWPS. */ | |
210 | + | |
211 | + if (ptid_get_lwp (inferior_ptid) == 0) | |
212 | + i386_linux_dr_set (inferior_ptid, DR_CONTROL, control); | |
213 | + else | |
214 | + { | |
215 | + struct lwp_info *lp; | |
216 | + ptid_t ptid; | |
217 | + | |
218 | + ALL_LWPS (lp, ptid) | |
219 | + i386_linux_dr_set (ptid, DR_CONTROL, control); | |
220 | + } | |
221 | } | |
222 | ||
223 | void | |
224 | i386_linux_dr_set_addr (int regnum, CORE_ADDR addr) | |
225 | { | |
226 | - struct lwp_info *lp; | |
227 | - ptid_t ptid; | |
228 | - | |
229 | gdb_assert (regnum >= 0 && regnum <= DR_LASTADDR - DR_FIRSTADDR); | |
230 | ||
231 | i386_linux_dr[DR_FIRSTADDR + regnum] = addr; | |
232 | - ALL_LWPS (lp, ptid) | |
233 | - i386_linux_dr_set (ptid, DR_FIRSTADDR + regnum, addr); | |
234 | + | |
235 | + /* I386_DETACH_BREAKPOINTS may need to reset the registers on single process | |
236 | + not listed for ALL_LWPS. */ | |
237 | + | |
238 | + if (ptid_get_lwp (inferior_ptid) == 0) | |
239 | + i386_linux_dr_set (inferior_ptid, DR_FIRSTADDR + regnum, addr); | |
240 | + else | |
241 | + { | |
242 | + struct lwp_info *lp; | |
243 | + ptid_t ptid; | |
244 | + | |
245 | + ALL_LWPS (lp, ptid) | |
246 | + i386_linux_dr_set (ptid, DR_FIRSTADDR + regnum, addr); | |
247 | + } | |
248 | } | |
249 | ||
250 | void | |
251 | @@ -673,6 +694,41 @@ i386_linux_new_thread (ptid_t ptid) | |
252 | ||
253 | i386_linux_dr_set (ptid, DR_CONTROL, i386_linux_dr[DR_CONTROL]); | |
254 | } | |
255 | + | |
256 | +/* TO_FOLLOW_FORK stores here the PID under DETACH_BREAKPOINTS for the child | |
257 | + process of traced FORK. We must clear such watchpoints only once during | |
258 | + DETACH_BREAKPOINTS. */ | |
259 | + | |
260 | +static int i386_linux_detach_breakpoints_pid; | |
261 | + | |
262 | +/* Remove a watchpoint that watched the memory region which starts at | |
263 | + address ADDR, whose length is LEN bytes, and for accesses of the | |
264 | + type TYPE. Return 0 on success, -1 on failure. */ | |
265 | +int | |
266 | +i386_linux_remove_watchpoint (CORE_ADDR addr, int len, int type) | |
267 | +{ | |
268 | + if (ptid_get_pid (inferior_ptid) == i386_linux_detach_breakpoints_pid) | |
269 | + return 0; | |
270 | + /* FOLLOW-FORK-MODE CHILD runs later the CHILD with no restrictions. */ | |
271 | + i386_linux_detach_breakpoints_pid = 0; | |
272 | + | |
273 | + return i386_remove_watchpoint (addr, len, type); | |
274 | +} | |
275 | + | |
276 | +static void | |
277 | +i386_linux_detach_breakpoints (int detached_pid) | |
278 | +{ | |
279 | + struct cleanup *old_chain = save_inferior_ptid (); | |
280 | + int i; | |
281 | + | |
282 | + i386_linux_detach_breakpoints_pid = detached_pid; | |
283 | + /* Depend on `!is_lwp (inferior_ptid)' for the I386_* macros. */ | |
284 | + inferior_ptid = pid_to_ptid (detached_pid); | |
285 | + | |
286 | + i386_detach_breakpoints (detached_pid); | |
287 | + | |
288 | + do_cleanups (old_chain); | |
289 | +} | |
290 | \f | |
291 | ||
292 | /* Called by libthread_db. Returns a pointer to the thread local | |
293 | @@ -812,6 +868,40 @@ i386_linux_child_post_startup_inferior ( | |
294 | super_post_startup_inferior (ptid); | |
295 | } | |
296 | ||
297 | +static int (*i386_linux_super_follow_fork) (struct target_ops *ops, | |
298 | + int follow_child); | |
299 | + | |
300 | +/* We need to duplicate the LINUX_CHILD_FOLLOW_FORK behavior here and catch its | |
301 | + called DETACH_BREAKPOINTS to avoid corrupting our local registers mirror. */ | |
302 | + | |
303 | +static int | |
304 | +i386_linux_follow_fork (struct target_ops *ops, int follow_child) | |
305 | +{ | |
306 | + ptid_t last_ptid; | |
307 | + struct target_waitstatus last_status; | |
308 | + int has_vforked; | |
309 | + int parent_pid, child_pid; | |
310 | + | |
311 | + get_last_target_status (&last_ptid, &last_status); | |
312 | + has_vforked = (last_status.kind == TARGET_WAITKIND_VFORKED); | |
313 | + parent_pid = ptid_get_lwp (last_ptid); | |
314 | + if (parent_pid == 0) | |
315 | + parent_pid = ptid_get_pid (last_ptid); | |
316 | + child_pid = ptid_get_pid (last_status.value.related_pid); | |
317 | + | |
318 | + if (! follow_child) | |
319 | + { | |
320 | + i386_linux_detach_breakpoints (child_pid); | |
321 | + } | |
322 | + else | |
323 | + { | |
324 | + if (! has_vforked) | |
325 | + i386_linux_detach_breakpoints (child_pid); | |
326 | + } | |
327 | + | |
328 | + return (*i386_linux_super_follow_fork) (ops, follow_child); | |
329 | +} | |
330 | + | |
331 | void | |
332 | _initialize_i386_linux_nat (void) | |
333 | { | |
334 | @@ -833,6 +923,9 @@ _initialize_i386_linux_nat (void) | |
335 | t->to_fetch_registers = i386_linux_fetch_inferior_registers; | |
336 | t->to_store_registers = i386_linux_store_inferior_registers; | |
337 | ||
338 | + i386_linux_super_follow_fork = t->to_follow_fork; | |
339 | + t->to_follow_fork = i386_linux_follow_fork; | |
340 | + | |
341 | /* Register the target. */ | |
342 | linux_nat_add_target (t); | |
343 | linux_nat_set_new_thread (t, i386_linux_new_thread); | |
344 | Index: gdb-6.8.50.20090209/gdb/i386-nat.c | |
345 | =================================================================== | |
346 | --- gdb-6.8.50.20090209.orig/gdb/i386-nat.c 2009-01-03 06:57:51.000000000 +0100 | |
347 | +++ gdb-6.8.50.20090209/gdb/i386-nat.c 2009-02-09 16:02:42.000000000 +0100 | |
348 | @@ -546,6 +546,17 @@ i386_remove_watchpoint (CORE_ADDR addr, | |
349 | return retval; | |
350 | } | |
351 | ||
352 | +void | |
353 | +i386_detach_breakpoints (int detached_pid) | |
354 | +{ | |
355 | + int i; | |
356 | + | |
357 | + /* Do not touch any DR_MIRROR or DR_CONTROL_MIRROR mirrors here. */ | |
358 | + I386_DR_LOW_SET_CONTROL (0); | |
359 | + ALL_DEBUG_REGISTERS(i) | |
360 | + I386_DR_LOW_RESET_ADDR (i); | |
361 | +} | |
362 | + | |
363 | /* Return non-zero if we can watch a memory region that starts at | |
364 | address ADDR and whose length is LEN bytes. */ | |
365 | ||
366 | Index: gdb-6.8.50.20090209/gdb/ia64-linux-nat.c | |
367 | =================================================================== | |
368 | --- gdb-6.8.50.20090209.orig/gdb/ia64-linux-nat.c 2009-02-09 15:48:43.000000000 +0100 | |
369 | +++ gdb-6.8.50.20090209/gdb/ia64-linux-nat.c 2009-02-09 16:02:42.000000000 +0100 | |
370 | @@ -583,6 +583,12 @@ ia64_linux_insert_watchpoint (CORE_ADDR | |
371 | return 0; | |
372 | } | |
373 | ||
374 | +/* TO_FOLLOW_FORK stores here the PID under DETACH_BREAKPOINTS for the child | |
375 | + process of traced FORK. We must clear such watchpoints only once during | |
376 | + DETACH_BREAKPOINTS. */ | |
377 | + | |
378 | +static int ia64_linux_detach_breakpoints_pid; | |
379 | + | |
380 | static int | |
381 | ia64_linux_remove_watchpoint (CORE_ADDR addr, int len, int type) | |
382 | { | |
383 | @@ -590,6 +596,11 @@ ia64_linux_remove_watchpoint (CORE_ADDR | |
384 | long dbr_addr, dbr_mask; | |
385 | int max_watchpoints = 4; | |
386 | ||
387 | + if (ptid_get_pid (inferior_ptid) == ia64_linux_detach_breakpoints_pid) | |
388 | + return 0; | |
389 | + /* FOLLOW-FORK-MODE CHILD runs later the CHILD with no restrictions. */ | |
390 | + ia64_linux_detach_breakpoints_pid = 0; | |
391 | + | |
392 | if (len <= 0 || !is_power_of_2 (len)) | |
393 | return -1; | |
394 | ||
395 | @@ -617,6 +628,22 @@ ia64_linux_remove_watchpoint (CORE_ADDR | |
396 | } | |
397 | ||
398 | static void | |
399 | +ia64_linux_detach_breakpoints (int detached_pid) | |
400 | +{ | |
401 | + int idx, i; | |
402 | + long dbr_addr, dbr_mask; | |
403 | + int max_watchpoints = 4; | |
404 | + | |
405 | + ia64_linux_detach_breakpoints_pid = detached_pid; | |
406 | + | |
407 | + /* Do not touch any DEBUG_REGISTERS mirrors here. */ | |
408 | + dbr_addr = 0; | |
409 | + dbr_mask = 0; | |
410 | + for (idx = 0; idx < max_watchpoints; idx++) | |
411 | + store_debug_register_pair (ptid_build (detached_pid, 0, 0), idx, &dbr_addr, &dbr_mask); | |
412 | +} | |
413 | + | |
414 | +static void | |
415 | ia64_linux_new_thread (ptid_t ptid) | |
416 | { | |
417 | int i, any; | |
418 | @@ -805,6 +832,40 @@ ia64_linux_xfer_partial (struct target_o | |
419 | offset, len); | |
420 | } | |
421 | ||
422 | +static int (*ia64_linux_super_follow_fork) (struct target_ops *ops, | |
423 | + int follow_child); | |
424 | + | |
425 | +/* We need to duplicate the LINUX_CHILD_FOLLOW_FORK behavior here and catch its | |
426 | + called DETACH_BREAKPOINTS to avoid corrupting our local registers mirror. */ | |
427 | + | |
428 | +int | |
429 | +ia64_linux_follow_fork (struct target_ops *ops, int follow_child) | |
430 | +{ | |
431 | + ptid_t last_ptid; | |
432 | + struct target_waitstatus last_status; | |
433 | + int has_vforked; | |
434 | + int parent_pid, child_pid; | |
435 | + | |
436 | + get_last_target_status (&last_ptid, &last_status); | |
437 | + has_vforked = (last_status.kind == TARGET_WAITKIND_VFORKED); | |
438 | + parent_pid = ptid_get_lwp (last_ptid); | |
439 | + if (parent_pid == 0) | |
440 | + parent_pid = ptid_get_pid (last_ptid); | |
441 | + child_pid = ptid_get_pid (last_status.value.related_pid); | |
442 | + | |
443 | + if (! follow_child) | |
444 | + { | |
445 | + ia64_linux_detach_breakpoints (child_pid); | |
446 | + } | |
447 | + else | |
448 | + { | |
449 | + if (! has_vforked) | |
450 | + ia64_linux_detach_breakpoints (child_pid); | |
451 | + } | |
452 | + | |
453 | + return (*ia64_linux_super_follow_fork) (ops, follow_child); | |
454 | +} | |
455 | + | |
456 | void _initialize_ia64_linux_nat (void); | |
457 | ||
458 | /* | |
459 | @@ -899,6 +960,9 @@ _initialize_ia64_linux_nat (void) | |
460 | t->to_insert_watchpoint = ia64_linux_insert_watchpoint; | |
461 | t->to_remove_watchpoint = ia64_linux_remove_watchpoint; | |
462 | ||
463 | + ia64_linux_super_follow_fork = t->to_follow_fork; | |
464 | + t->to_follow_fork = ia64_linux_follow_fork; | |
465 | + | |
466 | /* Register the target. */ | |
467 | linux_nat_add_target (t); | |
468 | linux_nat_set_new_thread (t, ia64_linux_new_thread); | |
469 | Index: gdb-6.8.50.20090209/gdb/ppc-linux-nat.c | |
470 | =================================================================== | |
471 | --- gdb-6.8.50.20090209.orig/gdb/ppc-linux-nat.c 2009-01-03 06:57:52.000000000 +0100 | |
472 | +++ gdb-6.8.50.20090209/gdb/ppc-linux-nat.c 2009-02-09 16:02:42.000000000 +0100 | |
473 | @@ -1118,6 +1118,12 @@ ppc_linux_insert_watchpoint (CORE_ADDR a | |
474 | return 0; | |
475 | } | |
476 | ||
477 | +/* TO_FOLLOW_FORK stores here the PID under DETACH_BREAKPOINTS for the child | |
478 | + process of traced FORK. We must clear such watchpoints only once during | |
479 | + DETACH_BREAKPOINTS. */ | |
480 | + | |
481 | +static int ppc_linux_detach_breakpoints_pid; | |
482 | + | |
483 | static int | |
484 | ppc_linux_remove_watchpoint (CORE_ADDR addr, int len, int rw) | |
485 | { | |
486 | @@ -1125,6 +1131,11 @@ ppc_linux_remove_watchpoint (CORE_ADDR a | |
487 | ptid_t ptid; | |
488 | long dabr_value = 0; | |
489 | ||
490 | + if (ptid_get_pid (inferior_ptid) == ppc_linux_detach_breakpoints_pid) | |
491 | + return 0; | |
492 | + /* FOLLOW-FORK-MODE CHILD runs later the CHILD with no restrictions. */ | |
493 | + ppc_linux_detach_breakpoints_pid = 0; | |
494 | + | |
495 | saved_dabr_value = 0; | |
496 | ALL_LWPS (lp, ptid) | |
497 | if (ptrace (PTRACE_SET_DEBUGREG, TIDGET (ptid), 0, saved_dabr_value) < 0) | |
498 | @@ -1138,6 +1149,15 @@ ppc_linux_new_thread (ptid_t ptid) | |
499 | ptrace (PTRACE_SET_DEBUGREG, TIDGET (ptid), 0, saved_dabr_value); | |
500 | } | |
501 | ||
502 | +static void | |
503 | +ppc_linux_detach_breakpoints (int detached_pid) | |
504 | +{ | |
505 | + ppc_linux_detach_breakpoints_pid = detached_pid; | |
506 | + | |
507 | + /* Do not touch the SAVED_DABR_VALUE mirror here. */ | |
508 | + ptrace (PTRACE_SET_DEBUGREG, detached_pid, 0, 0); | |
509 | +} | |
510 | + | |
511 | static int | |
512 | ppc_linux_stopped_data_address (struct target_ops *target, CORE_ADDR *addr_p) | |
513 | { | |
514 | @@ -1318,6 +1338,40 @@ ppc_linux_read_description (struct targe | |
515 | return isa205? tdesc_powerpc_isa205_32l : tdesc_powerpc_32l; | |
516 | } | |
517 | ||
518 | +static int (*ppc_linux_super_follow_fork) (struct target_ops *ops, | |
519 | + int follow_child); | |
520 | + | |
521 | +/* We need to duplicate the LINUX_CHILD_FOLLOW_FORK behavior here and catch its | |
522 | + called DETACH_BREAKPOINTS to avoid corrupting our local registers mirror. */ | |
523 | + | |
524 | +int | |
525 | +ppc_linux_follow_fork (struct target_ops *ops, int follow_child) | |
526 | +{ | |
527 | + ptid_t last_ptid; | |
528 | + struct target_waitstatus last_status; | |
529 | + int has_vforked; | |
530 | + int parent_pid, child_pid; | |
531 | + | |
532 | + get_last_target_status (&last_ptid, &last_status); | |
533 | + has_vforked = (last_status.kind == TARGET_WAITKIND_VFORKED); | |
534 | + parent_pid = ptid_get_lwp (last_ptid); | |
535 | + if (parent_pid == 0) | |
536 | + parent_pid = ptid_get_pid (last_ptid); | |
537 | + child_pid = ptid_get_pid (last_status.value.related_pid); | |
538 | + | |
539 | + if (! follow_child) | |
540 | + { | |
541 | + ppc_linux_detach_breakpoints (child_pid); | |
542 | + } | |
543 | + else | |
544 | + { | |
545 | + if (! has_vforked) | |
546 | + ppc_linux_detach_breakpoints (child_pid); | |
547 | + } | |
548 | + | |
549 | + return (*ppc_linux_super_follow_fork) (ops, follow_child); | |
550 | +} | |
551 | + | |
552 | void _initialize_ppc_linux_nat (void); | |
553 | ||
554 | void | |
555 | @@ -1343,6 +1397,9 @@ _initialize_ppc_linux_nat (void) | |
556 | ||
557 | t->to_read_description = ppc_linux_read_description; | |
558 | ||
559 | + ppc_linux_super_follow_fork = t->to_follow_fork; | |
560 | + t->to_follow_fork = ppc_linux_follow_fork; | |
561 | + | |
562 | /* Register the target. */ | |
563 | linux_nat_add_target (t); | |
564 | linux_nat_set_new_thread (t, ppc_linux_new_thread); | |
565 | Index: gdb-6.8.50.20090209/gdb/s390-nat.c | |
566 | =================================================================== | |
567 | --- gdb-6.8.50.20090209.orig/gdb/s390-nat.c 2007-11-07 07:36:57.000000000 +0100 | |
568 | +++ gdb-6.8.50.20090209/gdb/s390-nat.c 2009-02-09 16:02:42.000000000 +0100 | |
569 | @@ -283,21 +283,15 @@ s390_stopped_by_watchpoint (void) | |
570 | } | |
571 | ||
572 | static void | |
573 | -s390_fix_watch_points (ptid_t ptid) | |
574 | +s390_fix_watch_points_list (int tid, struct watch_area *area_list) | |
575 | { | |
576 | - int tid; | |
577 | - | |
578 | per_struct per_info; | |
579 | ptrace_area parea; | |
580 | ||
581 | CORE_ADDR watch_lo_addr = (CORE_ADDR)-1, watch_hi_addr = 0; | |
582 | struct watch_area *area; | |
583 | ||
584 | - tid = TIDGET (ptid); | |
585 | - if (tid == 0) | |
586 | - tid = PIDGET (ptid); | |
587 | - | |
588 | - for (area = watch_base; area; area = area->next) | |
589 | + for (area = area_list; area; area = area->next) | |
590 | { | |
591 | watch_lo_addr = min (watch_lo_addr, area->lo_addr); | |
592 | watch_hi_addr = max (watch_hi_addr, area->hi_addr); | |
593 | @@ -309,7 +303,7 @@ s390_fix_watch_points (ptid_t ptid) | |
594 | if (ptrace (PTRACE_PEEKUSR_AREA, tid, &parea) < 0) | |
595 | perror_with_name (_("Couldn't retrieve watchpoint status")); | |
596 | ||
597 | - if (watch_base) | |
598 | + if (area_list) | |
599 | { | |
600 | per_info.control_regs.bits.em_storage_alteration = 1; | |
601 | per_info.control_regs.bits.storage_alt_space_ctl = 1; | |
602 | @@ -326,6 +320,18 @@ s390_fix_watch_points (ptid_t ptid) | |
603 | perror_with_name (_("Couldn't modify watchpoint status")); | |
604 | } | |
605 | ||
606 | +static void | |
607 | +s390_fix_watch_points (ptid_t ptid) | |
608 | +{ | |
609 | + int tid; | |
610 | + | |
611 | + tid = TIDGET (ptid); | |
612 | + if (tid == 0) | |
613 | + tid = PIDGET (ptid); | |
614 | + | |
615 | + s390_fix_watch_points_list (tid, watch_base); | |
616 | +} | |
617 | + | |
618 | static int | |
619 | s390_insert_watchpoint (CORE_ADDR addr, int len, int type) | |
620 | { | |
621 | @@ -347,6 +353,12 @@ s390_insert_watchpoint (CORE_ADDR addr, | |
622 | return 0; | |
623 | } | |
624 | ||
625 | +/* TO_FOLLOW_FORK stores here the PID under DETACH_BREAKPOINTS for the child | |
626 | + process of traced FORK. We must clear such watchpoints only once during | |
627 | + DETACH_BREAKPOINTS. */ | |
628 | + | |
629 | +static int s390_detach_breakpoints_pid; | |
630 | + | |
631 | static int | |
632 | s390_remove_watchpoint (CORE_ADDR addr, int len, int type) | |
633 | { | |
634 | @@ -354,6 +366,11 @@ s390_remove_watchpoint (CORE_ADDR addr, | |
635 | ptid_t ptid; | |
636 | struct watch_area *area, **parea; | |
637 | ||
638 | + if (ptid_get_pid (inferior_ptid) == s390_detach_breakpoints_pid) | |
639 | + return 0; | |
640 | + /* FOLLOW-FORK-MODE CHILD runs later the CHILD with no restrictions. */ | |
641 | + s390_detach_breakpoints_pid = 0; | |
642 | + | |
643 | for (parea = &watch_base; *parea; parea = &(*parea)->next) | |
644 | if ((*parea)->lo_addr == addr | |
645 | && (*parea)->hi_addr == addr + len - 1) | |
646 | @@ -361,8 +378,10 @@ s390_remove_watchpoint (CORE_ADDR addr, | |
647 | ||
648 | if (!*parea) | |
649 | { | |
650 | +#if 0 /* Red Hat fork/threads watchpoints changes may trigger it. */ | |
651 | fprintf_unfiltered (gdb_stderr, | |
652 | "Attempt to remove nonexistent watchpoint.\n"); | |
653 | +#endif | |
654 | return -1; | |
655 | } | |
656 | ||
657 | @@ -375,6 +394,15 @@ s390_remove_watchpoint (CORE_ADDR addr, | |
658 | return 0; | |
659 | } | |
660 | ||
661 | +static void | |
662 | +s390_detach_breakpoints (int detached_pid) | |
663 | +{ | |
664 | + s390_detach_breakpoints_pid = detached_pid; | |
665 | + | |
666 | + /* Do not touch the WATCH_BASE here. */ | |
667 | + s390_fix_watch_points_list (detached_pid, NULL); | |
668 | +} | |
669 | + | |
670 | static int | |
671 | s390_can_use_hw_breakpoint (int type, int cnt, int othertype) | |
672 | { | |
673 | @@ -387,6 +415,39 @@ s390_region_ok_for_hw_watchpoint (CORE_A | |
674 | return 1; | |
675 | } | |
676 | ||
677 | +static int (*s390_super_follow_fork) (struct target_ops *ops, int follow_child); | |
678 | + | |
679 | +/* We need to duplicate the LINUX_CHILD_FOLLOW_FORK behavior here and catch its | |
680 | + called DETACH_BREAKPOINTS to avoid corrupting our local registers mirror. */ | |
681 | + | |
682 | +int | |
683 | +s390_follow_fork (struct target_ops *ops, int follow_child) | |
684 | +{ | |
685 | + ptid_t last_ptid; | |
686 | + struct target_waitstatus last_status; | |
687 | + int has_vforked; | |
688 | + int parent_pid, child_pid; | |
689 | + | |
690 | + get_last_target_status (&last_ptid, &last_status); | |
691 | + has_vforked = (last_status.kind == TARGET_WAITKIND_VFORKED); | |
692 | + parent_pid = ptid_get_lwp (last_ptid); | |
693 | + if (parent_pid == 0) | |
694 | + parent_pid = ptid_get_pid (last_ptid); | |
695 | + child_pid = ptid_get_pid (last_status.value.related_pid); | |
696 | + | |
697 | + if (! follow_child) | |
698 | + { | |
699 | + s390_detach_breakpoints (child_pid); | |
700 | + } | |
701 | + else | |
702 | + { | |
703 | + if (! has_vforked) | |
704 | + s390_detach_breakpoints (child_pid); | |
705 | + } | |
706 | + | |
707 | + return (*s390_super_follow_fork) (ops, follow_child); | |
708 | +} | |
709 | + | |
710 | ||
711 | void _initialize_s390_nat (void); | |
712 | ||
713 | @@ -410,6 +471,9 @@ _initialize_s390_nat (void) | |
714 | t->to_insert_watchpoint = s390_insert_watchpoint; | |
715 | t->to_remove_watchpoint = s390_remove_watchpoint; | |
716 | ||
717 | + s390_super_follow_fork = t->to_follow_fork; | |
718 | + t->to_follow_fork = s390_follow_fork; | |
719 | + | |
720 | /* Register the target. */ | |
721 | linux_nat_add_target (t); | |
722 | linux_nat_set_new_thread (t, s390_fix_watch_points); | |
723 | Index: gdb-6.8.50.20090209/gdb/testsuite/gdb.threads/watchpoint-fork-forkoff.c | |
724 | =================================================================== | |
725 | --- /dev/null 1970-01-01 00:00:00.000000000 +0000 | |
726 | +++ gdb-6.8.50.20090209/gdb/testsuite/gdb.threads/watchpoint-fork-forkoff.c 2009-02-09 16:02:42.000000000 +0100 | |
727 | @@ -0,0 +1,172 @@ | |
728 | +/* Test case for forgotten hw-watchpoints after fork()-off of a process. | |
729 | + | |
730 | + Copyright 2008 | |
731 | + Free Software Foundation, Inc. | |
732 | + | |
733 | + This file is part of GDB. | |
734 | + | |
735 | + This program is free software; you can redistribute it and/or modify | |
736 | + it under the terms of the GNU General Public License as published by | |
737 | + the Free Software Foundation; either version 2 of the License, or | |
738 | + (at your option) any later version. | |
739 | + | |
740 | + This program is distributed in the hope that it will be useful, | |
741 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | |
742 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
743 | + GNU General Public License for more details. | |
744 | + | |
745 | + You should have received a copy of the GNU General Public License | |
746 | + along with this program; if not, write to the Free Software | |
747 | + Foundation, Inc., 59 Temple Place - Suite 330, | |
748 | + Boston, MA 02111-1307, USA. */ | |
749 | + | |
750 | +#include <string.h> | |
751 | +#include <errno.h> | |
752 | + | |
753 | +static void delay (void) | |
754 | +{ | |
755 | + int i = usleep (1000000 / 100); | |
756 | + assert (i == 0 || errno == EINTR); | |
757 | +} | |
758 | + | |
759 | +#if defined FOLLOW_PARENT | |
760 | + | |
761 | +static void forkoff (int nr) | |
762 | +{ | |
763 | + pid_t child, pid_got; | |
764 | + int exit_code = 42 + nr; | |
765 | + int status, i; | |
766 | + | |
767 | + child = fork (); | |
768 | + switch (child) | |
769 | + { | |
770 | + case -1: | |
771 | + assert (0); | |
772 | + case 0: | |
773 | + printf ("child%d: %d\n", nr, (int) getpid ()); | |
774 | + /* Delay to get both the "child%d" and "parent%d" message printed without | |
775 | + a race breaking expect by its endless wait on `$gdb_prompt$': | |
776 | + Breakpoint 3, breakpoint () at ../../../gdb/testsuite/gdb.threads/watchpoint-fork.c:33 | |
777 | + 33 } | |
778 | + (gdb) parent2: 14223 */ | |
779 | + i = sleep (1); | |
780 | + assert (i == 0); | |
781 | + | |
782 | + /* We must not get caught here (against a forgotten breakpoint). */ | |
783 | + var++; | |
784 | + breakpoint (); | |
785 | + | |
786 | + _exit (exit_code); | |
787 | + default: | |
788 | + printf ("parent%d: %d\n", nr, (int) child); | |
789 | + /* Delay to get both the "child%d" and "parent%d" message printed, see | |
790 | + above. */ | |
791 | + i = sleep (1); | |
792 | + assert (i == 0); | |
793 | + | |
794 | + pid_got = wait (&status); | |
795 | + assert (pid_got == child); | |
796 | + assert (WIFEXITED (status)); | |
797 | + assert (WEXITSTATUS (status) == exit_code); | |
798 | + | |
799 | + /* We must get caught here (against a false watchpoint removal). */ | |
800 | + breakpoint (); | |
801 | + } | |
802 | +} | |
803 | + | |
804 | +#elif defined FOLLOW_CHILD | |
805 | + | |
806 | +static volatile int usr1_got; | |
807 | + | |
808 | +static void handler_usr1 (int signo) | |
809 | +{ | |
810 | + usr1_got++; | |
811 | +} | |
812 | + | |
813 | +static void forkoff (int nr) | |
814 | +{ | |
815 | + pid_t child; | |
816 | + int i, loop; | |
817 | + struct sigaction act, oldact; | |
818 | +#ifdef THREAD | |
819 | + void *thread_result; | |
820 | +#endif | |
821 | + | |
822 | + memset (&act, 0, sizeof act); | |
823 | + act.sa_flags = SA_RESTART; | |
824 | + act.sa_handler = handler_usr1; | |
825 | + sigemptyset (&act.sa_mask); | |
826 | + i = sigaction (SIGUSR1, &act, &oldact); | |
827 | + assert (i == 0); | |
828 | + | |
829 | + child = fork (); | |
830 | + switch (child) | |
831 | + { | |
832 | + case -1: | |
833 | + assert (0); | |
834 | + default: | |
835 | + printf ("parent%d: %d\n", nr, (int) child); | |
836 | + | |
837 | + /* Sleep for a while to possibly get incorrectly ATTACH_THREADed by GDB | |
838 | + tracing the child fork with no longer valid thread/lwp entries of the | |
839 | + parent. */ | |
840 | + | |
841 | + i = sleep (2); | |
842 | + assert (i == 0); | |
843 | + | |
844 | + /* We must not get caught here (against a forgotten breakpoint). */ | |
845 | + | |
846 | + var++; | |
847 | + breakpoint (); | |
848 | + | |
849 | +#ifdef THREAD | |
850 | + /* And neither got caught our thread. */ | |
851 | + | |
852 | + step = 99; | |
853 | + i = pthread_join (thread, &thread_result); | |
854 | + assert (i == 0); | |
855 | + assert (thread_result == (void *) 99UL); | |
856 | +#endif | |
857 | + | |
858 | + /* Be sure our child knows we did not get caught above. */ | |
859 | + | |
860 | + i = kill (child, SIGUSR1); | |
861 | + assert (i == 0); | |
862 | + | |
863 | + /* Sleep for a while to check GDB's `info threads' no longer tracks us in | |
864 | + the child fork. */ | |
865 | + | |
866 | + i = sleep (2); | |
867 | + assert (i == 0); | |
868 | + | |
869 | + _exit (0); | |
870 | + case 0: | |
871 | + printf ("child%d: %d\n", nr, (int) getpid ()); | |
872 | + | |
873 | + /* Let the parent signal us about its success. Be careful of races. */ | |
874 | + | |
875 | + for (loop = 0; loop < 1000; loop++) | |
876 | + { | |
877 | + /* Parent either died (and USR1_GOT is zero) or it succeeded. */ | |
878 | + if (kill (getppid (), 0) != 0) | |
879 | + break; | |
880 | + /* Parent succeeded? */ | |
881 | + if (usr1_got) | |
882 | + break; | |
883 | + | |
884 | + delay (); | |
885 | + } | |
886 | + assert (usr1_got); | |
887 | + | |
888 | + /* We must get caught here (against a false watchpoint removal). */ | |
889 | + | |
890 | + breakpoint (); | |
891 | + } | |
892 | + | |
893 | + i = sigaction (SIGUSR1, &oldact, NULL); | |
894 | + assert (i == 0); | |
895 | +} | |
896 | + | |
897 | +#else | |
898 | +# error "!FOLLOW_PARENT && !FOLLOW_CHILD" | |
899 | +#endif | |
900 | Index: gdb-6.8.50.20090209/gdb/testsuite/gdb.threads/watchpoint-fork-mt.c | |
901 | =================================================================== | |
902 | --- /dev/null 1970-01-01 00:00:00.000000000 +0000 | |
903 | +++ gdb-6.8.50.20090209/gdb/testsuite/gdb.threads/watchpoint-fork-mt.c 2009-02-09 16:02:42.000000000 +0100 | |
904 | @@ -0,0 +1,154 @@ | |
905 | +/* Test case for forgotten hw-watchpoints after fork()-off of a process. | |
906 | + | |
907 | + Copyright 2008 | |
908 | + Free Software Foundation, Inc. | |
909 | + | |
910 | + This file is part of GDB. | |
911 | + | |
912 | + This program is free software; you can redistribute it and/or modify | |
913 | + it under the terms of the GNU General Public License as published by | |
914 | + the Free Software Foundation; either version 2 of the License, or | |
915 | + (at your option) any later version. | |
916 | + | |
917 | + This program is distributed in the hope that it will be useful, | |
918 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | |
919 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
920 | + GNU General Public License for more details. | |
921 | + | |
922 | + You should have received a copy of the GNU General Public License | |
923 | + along with this program; if not, write to the Free Software | |
924 | + Foundation, Inc., 59 Temple Place - Suite 330, | |
925 | + Boston, MA 02111-1307, USA. */ | |
926 | + | |
927 | +#include <assert.h> | |
928 | +#include <unistd.h> | |
929 | +#include <sys/wait.h> | |
930 | +#include <stdio.h> | |
931 | +#include <stdlib.h> | |
932 | +#include <pthread.h> | |
933 | + | |
934 | +#include <asm/unistd.h> | |
935 | +#include <unistd.h> | |
936 | +#define gettid() syscall (__NR_gettid) | |
937 | + | |
938 | +/* Non-atomic `var++' should not hurt as we synchronize the threads by the STEP | |
939 | + variable. Hit-comments need to be duplicite there to catch both at-stops | |
940 | + and behind-stops, depending on the target. */ | |
941 | + | |
942 | +static volatile int var; | |
943 | + | |
944 | +static void dummy (void) | |
945 | +{ | |
946 | +} | |
947 | + | |
948 | +static void breakpoint (void) | |
949 | +{ | |
950 | +} | |
951 | + | |
952 | +/* Include here the functions: | |
953 | + static void forkoff (int nr); | |
954 | + static void delay (void); */ | |
955 | + | |
956 | +static pthread_t thread; | |
957 | +static volatile int step; | |
958 | +#define THREAD | |
959 | + | |
960 | +#include "watchpoint-fork-forkoff.c" | |
961 | + | |
962 | +static void *start (void *arg) | |
963 | +{ | |
964 | + if (step >= 3) | |
965 | + goto step_3; | |
966 | + | |
967 | + while (step != 1) | |
968 | + delay (); | |
969 | + | |
970 | + var++; /* validity-thread-B */ | |
971 | + dummy (); /* validity-thread-B */ | |
972 | + step = 2; | |
973 | + while (step != 3) | |
974 | + { | |
975 | + if (step == 99) | |
976 | + goto step_99; | |
977 | + delay (); | |
978 | + } | |
979 | + | |
980 | +step_3: | |
981 | + if (step >= 5) | |
982 | + goto step_5; | |
983 | + | |
984 | + var++; /* after-fork1-B */ | |
985 | + dummy (); /* after-fork1-B */ | |
986 | + step = 4; | |
987 | + while (step != 5) | |
988 | + { | |
989 | + if (step == 99) | |
990 | + goto step_99; | |
991 | + delay (); | |
992 | + } | |
993 | + | |
994 | +step_5: | |
995 | + var++; /* after-fork2-B */ | |
996 | + dummy (); /* after-fork2-B */ | |
997 | + return (void *) 5UL; | |
998 | + | |
999 | +step_99: | |
1000 | + /* We must not get caught here (against a forgotten breakpoint). */ | |
1001 | + var++; | |
1002 | + breakpoint (); | |
1003 | + return (void *) 99UL; | |
1004 | +} | |
1005 | + | |
1006 | +int main (void) | |
1007 | +{ | |
1008 | + int i; | |
1009 | + void *thread_result; | |
1010 | + | |
1011 | + setbuf (stdout, NULL); | |
1012 | + printf ("main: %d\n", (int) gettid ()); | |
1013 | + | |
1014 | + /* General watchpoints validity. */ | |
1015 | + var++; /* validity-first */ | |
1016 | + dummy (); /* validity-first */ | |
1017 | + | |
1018 | + i = pthread_create (&thread, NULL, start, NULL); | |
1019 | + assert (i == 0); | |
1020 | + | |
1021 | + var++; /* validity-thread-A */ | |
1022 | + dummy (); /* validity-thread-A */ | |
1023 | + step = 1; | |
1024 | + while (step != 2) | |
1025 | + delay (); | |
1026 | + | |
1027 | + /* Hardware watchpoints got disarmed here. */ | |
1028 | + forkoff (1); | |
1029 | + | |
1030 | + var++; /* after-fork1-A */ | |
1031 | + dummy (); /* after-fork1-A */ | |
1032 | + step = 3; | |
1033 | +#ifdef FOLLOW_CHILD | |
1034 | + /* Spawn new thread as it was deleted in the child of FORK. */ | |
1035 | + i = pthread_create (&thread, NULL, start, NULL); | |
1036 | + assert (i == 0); | |
1037 | +#endif | |
1038 | + while (step != 4) | |
1039 | + delay (); | |
1040 | + | |
1041 | + /* A sanity check for double hardware watchpoints removal. */ | |
1042 | + forkoff (2); | |
1043 | + | |
1044 | + var++; /* after-fork2-A */ | |
1045 | + dummy (); /* after-fork2-A */ | |
1046 | + step = 5; | |
1047 | +#ifdef FOLLOW_CHILD | |
1048 | + /* Spawn new thread as it was deleted in the child of FORK. */ | |
1049 | + i = pthread_create (&thread, NULL, start, NULL); | |
1050 | + assert (i == 0); | |
1051 | +#endif | |
1052 | + | |
1053 | + i = pthread_join (thread, &thread_result); | |
1054 | + assert (i == 0); | |
1055 | + assert (thread_result == (void *) 5UL); | |
1056 | + | |
1057 | + return 0; | |
1058 | +} | |
1059 | Index: gdb-6.8.50.20090209/gdb/testsuite/gdb.threads/watchpoint-fork.c | |
1060 | =================================================================== | |
1061 | --- /dev/null 1970-01-01 00:00:00.000000000 +0000 | |
1062 | +++ gdb-6.8.50.20090209/gdb/testsuite/gdb.threads/watchpoint-fork.c 2009-02-09 16:02:42.000000000 +0100 | |
1063 | @@ -0,0 +1,56 @@ | |
1064 | +/* Test case for forgotten hw-watchpoints after fork()-off of a process. | |
1065 | + | |
1066 | + Copyright 2008 | |
1067 | + Free Software Foundation, Inc. | |
1068 | + | |
1069 | + This file is part of GDB. | |
1070 | + | |
1071 | + This program is free software; you can redistribute it and/or modify | |
1072 | + it under the terms of the GNU General Public License as published by | |
1073 | + the Free Software Foundation; either version 2 of the License, or | |
1074 | + (at your option) any later version. | |
1075 | + | |
1076 | + This program is distributed in the hope that it will be useful, | |
1077 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | |
1078 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
1079 | + GNU General Public License for more details. | |
1080 | + | |
1081 | + You should have received a copy of the GNU General Public License | |
1082 | + along with this program; if not, write to the Free Software | |
1083 | + Foundation, Inc., 59 Temple Place - Suite 330, | |
1084 | + Boston, MA 02111-1307, USA. */ | |
1085 | + | |
1086 | +#include <assert.h> | |
1087 | +#include <unistd.h> | |
1088 | +#include <sys/wait.h> | |
1089 | +#include <stdio.h> | |
1090 | +#include <stdlib.h> | |
1091 | + | |
1092 | +static volatile int var; | |
1093 | + | |
1094 | +static void breakpoint (void) | |
1095 | +{ | |
1096 | +} | |
1097 | + | |
1098 | +/* Include here the function: | |
1099 | + static void forkoff (int nr); */ | |
1100 | + | |
1101 | +#include "watchpoint-fork-forkoff.c" | |
1102 | + | |
1103 | +int main (void) | |
1104 | +{ | |
1105 | + setbuf (stdout, NULL); | |
1106 | + printf ("main: %d\n", (int) getpid ()); | |
1107 | + | |
1108 | + /* General watchpoints validity. */ | |
1109 | + var++; | |
1110 | + /* Hardware watchpoints got disarmed here. */ | |
1111 | + forkoff (1); | |
1112 | + /* This watchpoint got lost before. */ | |
1113 | + var++; | |
1114 | + /* A sanity check for double hardware watchpoints removal. */ | |
1115 | + forkoff (2); | |
1116 | + var++; | |
1117 | + | |
1118 | + return 0; | |
1119 | +} | |
1120 | Index: gdb-6.8.50.20090209/gdb/testsuite/gdb.threads/watchpoint-fork.exp | |
1121 | =================================================================== | |
1122 | --- /dev/null 1970-01-01 00:00:00.000000000 +0000 | |
1123 | +++ gdb-6.8.50.20090209/gdb/testsuite/gdb.threads/watchpoint-fork.exp 2009-02-09 16:02:42.000000000 +0100 | |
1124 | @@ -0,0 +1,140 @@ | |
1125 | +# Copyright 2008 Free Software Foundation, Inc. | |
1126 | + | |
1127 | +# This program is free software; you can redistribute it and/or modify | |
1128 | +# it under the terms of the GNU General Public License as published by | |
1129 | +# the Free Software Foundation; either version 3 of the License, or | |
1130 | +# (at your option) any later version. | |
1131 | +# | |
1132 | +# This program is distributed in the hope that it will be useful, | |
1133 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
1134 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
1135 | +# GNU General Public License for more details. | |
1136 | +# | |
1137 | +# You should have received a copy of the GNU General Public License | |
1138 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
1139 | + | |
1140 | +# Test case for forgotten hw-watchpoints after fork()-off of a process. | |
1141 | + | |
1142 | +proc test {type symbol} { | |
1143 | + global objdir subdir srcdir | |
1144 | + | |
1145 | + global pf_prefix | |
1146 | + set prefix_test $pf_prefix | |
1147 | + lappend pf_prefix "$type:" | |
1148 | + set prefix_mt $pf_prefix | |
1149 | + | |
1150 | + # no threads | |
1151 | + | |
1152 | + set pf_prefix $prefix_mt | |
1153 | + lappend pf_prefix "singlethreaded:" | |
1154 | + | |
1155 | + set testfile watchpoint-fork | |
1156 | + set srcfile ${testfile}.c | |
1157 | + set binfile ${objdir}/${subdir}/${testfile} | |
1158 | + | |
1159 | + if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable "debug additional_flags=-D$symbol"] != "" } { | |
1160 | + untested "Couldn't compile test program" | |
1161 | + return -1 | |
1162 | + } | |
1163 | + | |
1164 | + gdb_exit | |
1165 | + gdb_start | |
1166 | + gdb_reinitialize_dir $srcdir/$subdir | |
1167 | + gdb_load ${binfile} | |
1168 | + | |
1169 | + gdb_test "set follow-fork-mode $type" | |
1170 | + # Testcase uses it for the `follow-fork-mode child' type. | |
1171 | + gdb_test "handle SIGUSR1 nostop noprint pass" | |
1172 | + | |
1173 | + if { ![runto_main] } then { | |
1174 | + gdb_suppress_tests | |
1175 | + return | |
1176 | + } | |
1177 | + | |
1178 | + # Install the watchpoint only after getting into MAIN - workaround some PPC | |
1179 | + # problem. | |
1180 | + gdb_test "watch var" "atchpoint 2: var" "Set the watchpoint" | |
1181 | + | |
1182 | + # It is never hit but it should not be left over in the fork()ed-off child. | |
1183 | + gdb_breakpoint "breakpoint" | |
1184 | + | |
1185 | + gdb_test "continue" \ | |
1186 | + "atchpoint 2: var.*Old value = 0.*New value = 1.*forkoff *\\(1\\).*" "watchpoints work" | |
1187 | + gdb_test "continue" \ | |
1188 | + "reakpoint 3, breakpoint.*" "breakpoint after the first fork" | |
1189 | + gdb_test "continue" \ | |
1190 | + "atchpoint 2: var.*Old value = 1.*New value = 2.*forkoff *\\(2\\).*" "watchpoint after the first fork" | |
1191 | + gdb_test "continue" \ | |
1192 | + "reakpoint 3, breakpoint.*" "breakpoint after the second fork" | |
1193 | + gdb_test "continue" \ | |
1194 | + "atchpoint 2: var.*Old value = 2.*New value = 3.*return *0;" "watchpoint after the second fork" | |
1195 | + gdb_test "continue" "Continuing..*Program exited normally." "finish" | |
1196 | + | |
1197 | + | |
1198 | + # threads | |
1199 | + | |
1200 | + set pf_prefix $prefix_mt | |
1201 | + lappend pf_prefix "multithreaded:" | |
1202 | + | |
1203 | + set testfile watchpoint-fork-mt | |
1204 | + set srcfile ${testfile}.c | |
1205 | + set binfile ${objdir}/${subdir}/${testfile} | |
1206 | + | |
1207 | + if { [gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable "debug additional_flags=-D$symbol"] != "" } { | |
1208 | + untested "Couldn't compile test program" | |
1209 | + return -1 | |
1210 | + } | |
1211 | + | |
1212 | + gdb_exit | |
1213 | + gdb_start | |
1214 | + gdb_reinitialize_dir $srcdir/$subdir | |
1215 | + gdb_load ${binfile} | |
1216 | + | |
1217 | + gdb_test "set follow-fork-mode $type" | |
1218 | + # Testcase uses it for the `follow-fork-mode child' type. | |
1219 | + gdb_test "handle SIGUSR1 nostop noprint pass" | |
1220 | + | |
1221 | + if { ![runto_main] } then { | |
1222 | + gdb_suppress_tests | |
1223 | + return | |
1224 | + } | |
1225 | + | |
1226 | + # Install the watchpoint only after getting into MAIN - workaround some PPC | |
1227 | + # problem. | |
1228 | + gdb_test "watch var" "atchpoint 2: var" "Set the watchpoint" | |
1229 | + | |
1230 | + # It is never hit but it should not be left over in the fork()ed-off child. | |
1231 | + gdb_breakpoint "breakpoint" | |
1232 | + | |
1233 | + gdb_test "continue" \ | |
1234 | + "atchpoint 2: var.*Old value = 0.*New value = 1.*validity-first.*" "singlethread watchpoints work" | |
1235 | + gdb_test "continue" \ | |
1236 | + "atchpoint 2: var.*Old value = 1.*New value = 2.*validity-thread-A.*" "multithreaded watchpoints work at A" | |
1237 | + gdb_test "continue" \ | |
1238 | + "atchpoint 2: var.*Old value = 2.*New value = 3.*validity-thread-B.*" "multithreaded watchpoints work at B" | |
1239 | + gdb_test "continue" \ | |
1240 | + "reakpoint 3, breakpoint.*" "breakpoint (A) after the first fork" | |
1241 | + gdb_test "continue" \ | |
1242 | + "atchpoint 2: var.*Old value = 3.*New value = 4.*after-fork1-A.*" "watchpoint A after the first fork" | |
1243 | + gdb_test "continue" \ | |
1244 | + "atchpoint 2: var.*Old value = 4.*New value = 5.*after-fork1-B.*" "watchpoint B after the first fork" | |
1245 | + gdb_test "continue" \ | |
1246 | + "reakpoint 3, breakpoint.*" "breakpoint (A) after the second fork" | |
1247 | + gdb_test "continue" \ | |
1248 | + "atchpoint 2: var.*Old value = 5.*New value = 6.*after-fork2-A.*" "watchpoint A after the second fork" | |
1249 | + gdb_test "continue" \ | |
1250 | + "atchpoint 2: var.*Old value = 6.*New value = 7.*after-fork2-B.*" "watchpoint B after the second fork" | |
1251 | + gdb_test "continue" "Continuing..*Program exited normally." "finish" | |
1252 | + | |
1253 | + | |
1254 | + # cleanup | |
1255 | + | |
1256 | + set pf_prefix $prefix_test | |
1257 | +} | |
1258 | + | |
1259 | +test parent FOLLOW_PARENT | |
1260 | + | |
1261 | +# Only GNU/Linux is known to support `set follow-fork-mode child'. | |
1262 | +if {[istarget "*-*-linux*"]} { | |
1263 | + test child FOLLOW_CHILD | |
1264 | +} | |
1265 | Index: gdb-6.8.50.20090209/gdb/doc/gdb.texinfo | |
1266 | =================================================================== | |
1267 | --- gdb-6.8.50.20090209.orig/gdb/doc/gdb.texinfo 2009-02-09 16:02:35.000000000 +0100 | |
1268 | +++ gdb-6.8.50.20090209/gdb/doc/gdb.texinfo 2009-02-09 16:02:42.000000000 +0100 | |
1269 | @@ -3588,6 +3588,14 @@ confident that no other thread can becom | |
1270 | software watchpoints as usual. However, @value{GDBN} may not notice | |
1271 | when a non-current thread's activity changes the expression. (Hardware | |
1272 | watchpoints, in contrast, watch an expression in all threads.) | |
1273 | + | |
1274 | +Software watchpoints single-step the current thread to track the changes. | |
1275 | +Other threads are left freely running on @code{continue}; therefore, their | |
1276 | +changes cannot be caught. To get more reliable software watchpoints, please | |
1277 | +use @code{set scheduler-locking on}. The default for Red Hat/Fedora | |
1278 | +@value{GDBN} is @code{set scheduler-locking step}, which makes the software | |
1279 | +watchpoints safe for the @code{step} command, but not for the @code{continue} | |
1280 | +command. @xref{Thread Stops}. | |
1281 | @end quotation | |
1282 | ||
1283 | @xref{set remote hardware-watchpoint-limit}. | |
1284 | Index: gdb-6.8.50.20090209/gdb/config/i386/nm-linux.h | |
1285 | =================================================================== | |
1286 | --- gdb-6.8.50.20090209.orig/gdb/config/i386/nm-linux.h 2009-01-03 06:57:54.000000000 +0100 | |
1287 | +++ gdb-6.8.50.20090209/gdb/config/i386/nm-linux.h 2009-02-09 16:02:42.000000000 +0100 | |
1288 | @@ -46,6 +46,16 @@ extern void i386_linux_dr_reset_addr (in | |
1289 | extern unsigned long i386_linux_dr_get_status (void); | |
1290 | #define I386_DR_LOW_GET_STATUS() \ | |
1291 | i386_linux_dr_get_status () | |
1292 | + | |
1293 | +/* Remove a watchpoint that watched the memory region which starts at | |
1294 | + * address ADDR, whose length is LEN bytes, and for accesses of the | |
1295 | + * type TYPE. Return 0 on success, -1 on failure. */ | |
1296 | +extern int i386_linux_remove_watchpoint (CORE_ADDR addr, int len, int type); | |
1297 | + | |
1298 | +/* Override basic i386 macros for watchpoint and hardware breakpoint | |
1299 | + insertion/removal to support threads. */ | |
1300 | +#define target_remove_watchpoint(addr, len, type) \ | |
1301 | + i386_linux_remove_watchpoint (addr, len, type) | |
1302 | \f | |
1303 | ||
1304 | #ifdef HAVE_PTRACE_GETFPXREGS | |
1305 | Index: gdb-6.8.50.20090209/gdb/config/i386/nm-linux64.h | |
1306 | =================================================================== | |
1307 | --- gdb-6.8.50.20090209.orig/gdb/config/i386/nm-linux64.h 2009-01-03 06:57:54.000000000 +0100 | |
1308 | +++ gdb-6.8.50.20090209/gdb/config/i386/nm-linux64.h 2009-02-09 16:02:42.000000000 +0100 | |
1309 | @@ -51,4 +51,14 @@ extern unsigned long amd64_linux_dr_get_ | |
1310 | #define I386_DR_LOW_GET_STATUS() \ | |
1311 | amd64_linux_dr_get_status () | |
1312 | ||
1313 | +/* Remove a watchpoint that watched the memory region which starts at | |
1314 | + * address ADDR, whose length is LEN bytes, and for accesses of the | |
1315 | + * type TYPE. Return 0 on success, -1 on failure. */ | |
1316 | +extern int amd64_linux_remove_watchpoint (CORE_ADDR addr, int len, int type); | |
1317 | + | |
1318 | +/* Override basic amd64 macros for watchpoint and hardware breakpoint | |
1319 | + insertion/removal to support threads. */ | |
1320 | +#define target_remove_watchpoint(addr, len, type) \ | |
1321 | + amd64_linux_remove_watchpoint (addr, len, type) | |
1322 | + | |
1323 | #endif /* nm-linux64.h */ | |
1324 | Index: gdb-6.8.50.20090209/gdb/target.h | |
1325 | =================================================================== | |
1326 | --- gdb-6.8.50.20090209.orig/gdb/target.h 2009-02-09 15:49:25.000000000 +0100 | |
1327 | +++ gdb-6.8.50.20090209/gdb/target.h 2009-02-09 16:02:42.000000000 +0100 | |
1328 | @@ -1113,7 +1113,9 @@ extern char *normal_pid_to_str (ptid_t p | |
1329 | #ifndef target_insert_watchpoint | |
1330 | #define target_insert_watchpoint(addr, len, type) \ | |
1331 | (*current_target.to_insert_watchpoint) (addr, len, type) | |
1332 | +#endif | |
1333 | ||
1334 | +#ifndef target_remove_watchpoint | |
1335 | #define target_remove_watchpoint(addr, len, type) \ | |
1336 | (*current_target.to_remove_watchpoint) (addr, len, type) | |
1337 | #endif |