diff options
-rw-r--r-- | gdb/infrun.c | 39 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/foll-fork.exp | 18 |
2 files changed, 48 insertions, 9 deletions
diff --git a/gdb/infrun.c b/gdb/infrun.c index 0acb3f7..5fd1ade 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -539,25 +539,46 @@ holding the child stopped. Try \"set detach-on-fork\" or \ child_inf->gdbarch = parent_inf->gdbarch; copy_inferior_target_desc_info (child_inf, parent_inf); - program_space *parent_pspace = parent_inf->pspace; - - /* If this is a vfork child, then the address-space is shared - with the parent. If we detached from the parent, then we can - reuse the parent's program/address spaces. */ - if (has_vforked || detach_fork) + if (has_vforked) { - child_inf->pspace = parent_pspace; - child_inf->aspace = child_inf->pspace->aspace; + /* If this is a vfork child, then the address-space is shared + with the parent. */ + child_inf->aspace = parent_inf->aspace; + child_inf->pspace = parent_inf->pspace; exec_on_vfork (child_inf); } + else if (detach_fork) + { + /* We follow the child and detach from the parent: move the parent's + program space to the child. This simplifies some things, like + doing "next" over fork() and landing on the expected line in the + child (note, that is broken with "set detach-on-fork off"). + + Before assigning brand new spaces for the parent, remove + breakpoints from it: because the new pspace won't match + currently inserted locations, the normal detach procedure + wouldn't remove them, and we would leave them inserted when + detaching. */ + remove_breakpoints_inf (parent_inf); + + child_inf->aspace = parent_inf->aspace; + child_inf->pspace = parent_inf->pspace; + parent_inf->aspace = new_address_space (); + parent_inf->pspace = new program_space (parent_inf->aspace); + clone_program_space (parent_inf->pspace, child_inf->pspace); + + /* The parent inferior is still the current one, so keep things + in sync. */ + set_current_program_space (parent_inf->pspace); + } else { child_inf->aspace = new_address_space (); child_inf->pspace = new program_space (child_inf->aspace); child_inf->removable = 1; child_inf->symfile_flags = SYMFILE_NO_READ; - clone_program_space (child_inf->pspace, parent_pspace); + clone_program_space (child_inf->pspace, parent_inf->pspace); } } diff --git a/gdb/testsuite/gdb.base/foll-fork.exp b/gdb/testsuite/gdb.base/foll-fork.exp index 3a0cc2f..7f9e1cf 100644 --- a/gdb/testsuite/gdb.base/foll-fork.exp +++ b/gdb/testsuite/gdb.base/foll-fork.exp @@ -181,6 +181,24 @@ proc_with_prefix test_follow_fork { follow-fork-mode detach-on-fork cmd } { ".* set breakpoint here.*" } } + + # If we end up with two inferiors, verify that they each end up with their + # own program space. Do this by setting a breakpoint, if we see two + # locations it means there are two program spaces. + if {${detach-on-fork} == "off" || ${follow-fork-mode} == "child"} { + set bpnum "<unset>" + gdb_test_multiple "break callee" "break callee" { + -re -wrap "Breakpoint ($::decimal) at $::hex: callee\\. \\(2 locations\\)" { + set bpnum $expect_out(1,string) + pass $gdb_test_name + } + } + gdb_test "info breakpoints $bpnum" \ + [multi_line \ + "$bpnum\\.1 .* inf 1" \ + "$bpnum\\.2 .* inf 2"] \ + "info breakpoints" + } } set reading_in_symbols_re {(?:\r\nReading in symbols for [^\r\n]*)?} |