diff options
author | Don Breazeal <donb@codesourcery.com> | 2015-05-12 09:52:44 -0700 |
---|---|---|
committer | Don Breazeal <donb@codesourcery.com> | 2015-05-12 09:52:44 -0700 |
commit | 3a8a0396bed4e9dd87c2df0f68386a0f04dfc824 (patch) | |
tree | 4fa6326b487196db58fe169e894d03edacaa2547 /gdb/gdbserver/linux-x86-low.c | |
parent | de0d863ec3fda88e488cee568f943c7998b68862 (diff) | |
download | gdb-3a8a0396bed4e9dd87c2df0f68386a0f04dfc824.zip gdb-3a8a0396bed4e9dd87c2df0f68386a0f04dfc824.tar.gz gdb-3a8a0396bed4e9dd87c2df0f68386a0f04dfc824.tar.bz2 |
Arch-specific remote follow fork
This patch implements the architecture-specific pieces of follow-fork
for remote and extended-remote Linux targets, which in the current
implementation copyies the parent's debug register state into the new
child's data structures. This is required for x86, arm, aarch64, and
mips.
This follows the native implementation as closely as possible by
implementing a new linux_target_ops function 'new_fork', which is
analogous to 'linux_nat_new_fork' in linux-nat.c. In gdbserver, the debug
registers are stored in the process list, instead of an
architecture-specific list, so the function arguments are process_info
pointers instead of an lwp_info and a pid as in the native implementation.
In the MIPS implementation the debug register mirror is stored differently
from x86, ARM, and aarch64, so instead of doing a simple structure assignment
I had to clone the list of watchpoint structures.
Tested using gdb.threads/watchpoint-fork.exp on x86, and ran manual tests
on a MIPS board and an ARM board. Aarch64 hasn't been tested.
gdb/gdbserver/ChangeLog:
* linux-aarch64-low.c (aarch64_linux_new_fork): New function.
(the_low_target) <new_fork>: Initialize new member.
* linux-arm-low.c (arm_new_fork): New function.
(the_low_target) <new_fork>: Initialize new member.
* linux-low.c (handle_extended_wait): Call new target function
new_fork.
* linux-low.h (struct linux_target_ops) <new_fork>: New member.
* linux-mips-low.c (mips_add_watchpoint): New function
extracted from mips_insert_point.
(the_low_target) <new_fork>: Initialize new member.
(mips_linux_new_fork): New function.
(mips_insert_point): Call mips_add_watchpoint.
* linux-x86-low.c (x86_linux_new_fork): New function.
(the_low_target) <new_fork>: Initialize new member.
Diffstat (limited to 'gdb/gdbserver/linux-x86-low.c')
-rw-r--r-- | gdb/gdbserver/linux-x86-low.c | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/gdb/gdbserver/linux-x86-low.c b/gdb/gdbserver/linux-x86-low.c index 763df08..4aef7b7 100644 --- a/gdb/gdbserver/linux-x86-low.c +++ b/gdb/gdbserver/linux-x86-low.c @@ -634,6 +634,34 @@ x86_linux_new_process (void) return info; } +/* Target routine for linux_new_fork. */ + +static void +x86_linux_new_fork (struct process_info *parent, struct process_info *child) +{ + /* These are allocated by linux_add_process. */ + gdb_assert (parent->priv != NULL + && parent->priv->arch_private != NULL); + gdb_assert (child->priv != NULL + && child->priv->arch_private != NULL); + + /* Linux kernel before 2.6.33 commit + 72f674d203cd230426437cdcf7dd6f681dad8b0d + will inherit hardware debug registers from parent + on fork/vfork/clone. Newer Linux kernels create such tasks with + zeroed debug registers. + + GDB core assumes the child inherits the watchpoints/hw + breakpoints of the parent, and will remove them all from the + forked off process. Copy the debug registers mirrors into the + new process so that all breakpoints and watchpoints can be + removed together. The debug registers mirror will become zeroed + in the end before detaching the forked off process, thus making + this compatible with older Linux kernels too. */ + + *child->priv->arch_private = *parent->priv->arch_private; +} + /* See nat/x86-dregs.h. */ struct x86_debug_reg_state * @@ -3263,6 +3291,7 @@ struct linux_target_ops the_low_target = x86_siginfo_fixup, x86_linux_new_process, x86_linux_new_thread, + x86_linux_new_fork, x86_linux_prepare_to_resume, x86_linux_process_qsupported, x86_supports_tracepoints, |