This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[commit] [1/3] watchpoints across vfork regressions - failed insertion detection
- From: Pedro Alves <pedro at codesourcery dot com>
- To: gdb-patches at sourceware dot org
- Date: Sun, 15 Nov 2009 21:45:18 +0000
- Subject: [commit] [1/3] watchpoints across vfork regressions - failed insertion detection
This fixes a regression Daniel noticed:
$ ./gdb ./gdb
...
(top-gdb) start
Temporary breakpoint 3 at 0x454627: file ../../src/gdb/gdb.c, line 28.
Starting program: /home/pedro/gdb/baseline/build/gdb/gdb
[Thread debugging using libthread_db enabled]
Temporary breakpoint 3, main (argc=
During symbol reading, incomplete CFI data; unspecified registers (e.g., rax) at 0x45461c.
1, argv=0x7fffffffe398) at ../../src/gdb/gdb.c:28
28 memset (&args, 0, sizeof args);
(top-gdb) watch selected_frame
During symbol reading, DW_AT_name missing from DW_TAG_base_type.
During symbol reading, unsupported tag: 'DW_TAG_const_type'.
During symbol reading, debug info gives in-file macro definition with zero line 0: __STDC__ 1.
Hardware watchpoint 4: selected_frame
(top-gdb) c
Continuing.
Warning:
Could not insert hardware watchpoint 4.
Could not insert hardware breakpoints:
You may have requested too many hardware breakpoints/watchpoints.
0x00007ffff6cb0ee4 in vfork () from /lib/libc.so.6
(top-gdb)
The vfork comes from find_charset_names -> pex_run
The watchpoint wasn't inserted, because waiting_for_vfork_done
is set on the parent, but, the code that checks for
failed-to-insert-watchpoints wasn't aware of the skipping.
I've checked it in. Patch 3/3 is a new test that covers
this use case.
Committed.
--
Pedro Alves
2009-11-15 Pedro Alves <pedro@codesourcery.com>
gdb/
* breakpoint.c (should_be_inserted): Don't insert breakpoints if
the pspace doesn't allow breakpoints.
(insert_breakpoint_locations): Remove waiting_for_vfork_done
special case. Expect watchpoints that shouldn't be inserted, to
not be inserted.
* progspace.h (struct program_space) <breakpoints_not_allowed>:
New field.
* infrun.c (handle_inferior_event): Clear it.
* linux-nat.c (linux_child_follow_fork): Set it.
---
gdb/breakpoint.c | 32 ++++++++++++--------------------
gdb/infrun.c | 1 +
gdb/linux-nat.c | 1 +
gdb/progspace.h | 4 ++++
4 files changed, 18 insertions(+), 20 deletions(-)
Index: src/gdb/breakpoint.c
===================================================================
--- src.orig/gdb/breakpoint.c 2009-11-15 19:45:34.000000000 +0000
+++ src/gdb/breakpoint.c 2009-11-15 19:46:32.000000000 +0000
@@ -1193,6 +1193,17 @@ should_be_inserted (struct bp_location *
if (!bpt->enabled || bpt->shlib_disabled || bpt->duplicate)
return 0;
+ /* This is set for example, when we're attached to the parent of a
+ vfork, and have detached from the child. The child is running
+ free, and we expect it to do an exec or exit, at which point the
+ OS makes the parent schedulable again (and the target reports
+ that the vfork is done). Until the child is done with the shared
+ memory region, do not insert breakpoints in the parent, otherwise
+ the child could still trip on the parent's breakpoints. Since
+ the parent is blocked anyway, it won't miss any breakpoint. */
+ if (bpt->pspace->breakpoints_not_allowed)
+ return 0;
+
/* Tracepoints are inserted by the target at a time of its choosing,
not by us. */
if (bpt->owner->type == bp_tracepoint)
@@ -1530,25 +1541,6 @@ insert_breakpoint_locations (void)
&& ptid_equal (inferior_ptid, null_ptid))
continue;
- if (!ptid_equal (inferior_ptid, null_ptid))
- {
- struct inferior *inf = current_inferior ();
- if (inf->waiting_for_vfork_done)
- {
- /* This is set when we're attached to the parent of the
- vfork, and have detached from the child. The child
- is running free, and we expect it to do an exec or
- exit, at which point the OS makes the parent
- schedulable again (and the target reports that the
- vfork is done). Until the child is done with the
- shared memory region, do not insert breakpoints in
- parent, otherwise the child could still trip on the
- parent's breakpoints. Since the parent is blocked
- anyway, it won't miss any breakpoint. */
- continue;
- }
- }
-
val = insert_bp_location (b, tmp_error_stream,
&disabled_breaks,
&hw_breakpoint_error);
@@ -1573,7 +1565,7 @@ insert_breakpoint_locations (void)
continue;
for (loc = bpt->loc; loc; loc = loc->next)
- if (!loc->inserted)
+ if (!loc->inserted && should_be_inserted (loc))
{
some_failed = 1;
break;
Index: src/gdb/progspace.h
===================================================================
--- src.orig/gdb/progspace.h 2009-11-15 19:45:34.000000000 +0000
+++ src/gdb/progspace.h 2009-11-15 19:45:53.000000000 +0000
@@ -165,6 +165,10 @@ struct program_space
to set breakpoints point at the wrong addresses. */
int executing_startup;
+ /* True if no breakpoints should be inserted in this program
+ space. */
+ int breakpoints_not_allowed;
+
/* The object file that the main symbol table was loaded from
(e.g. the argument to the "symbol-file" or "file" command). */
struct objfile *symfile_object_file;
Index: src/gdb/infrun.c
===================================================================
--- src.orig/gdb/infrun.c 2009-11-15 19:45:34.000000000 +0000
+++ src/gdb/infrun.c 2009-11-15 19:45:53.000000000 +0000
@@ -3004,6 +3004,7 @@ handle_inferior_event (struct execution_
context_switch (ecs->ptid);
current_inferior ()->waiting_for_vfork_done = 0;
+ current_inferior ()->pspace->breakpoints_not_allowed = 0;
/* This also takes care of reinserting breakpoints in the
previously locked inferior. */
keep_going (ecs);
Index: src/gdb/linux-nat.c
===================================================================
--- src.orig/gdb/linux-nat.c 2009-11-15 19:45:34.000000000 +0000
+++ src/gdb/linux-nat.c 2009-11-15 19:45:53.000000000 +0000
@@ -793,6 +793,7 @@ holding the child stopped. Try \"set de
subsequent child exec or exit is enough to know when does
the child stops using the parent's address space. */
parent_inf->waiting_for_vfork_done = detach_fork;
+ parent_inf->pspace->breakpoints_not_allowed = detach_fork;
lp = find_lwp_pid (pid_to_ptid (parent_pid));
gdb_assert (linux_supports_tracefork_flag >= 0);