aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Marchi <simon.marchi@polymtl.ca>2020-12-04 16:43:52 -0500
committerSimon Marchi <simon.marchi@efficios.com>2020-12-04 16:43:52 -0500
commitc0aba012edb6068e2433cbac855715a349a8555f (patch)
treefedba3cb6c177579da48a67e672024247be123a6
parent3b7a962dec0d5d852ad5f1338add07781adef7b4 (diff)
downloadgdb-c0aba012edb6068e2433cbac855715a349a8555f.zip
gdb-c0aba012edb6068e2433cbac855715a349a8555f.tar.gz
gdb-c0aba012edb6068e2433cbac855715a349a8555f.tar.bz2
gdb: restore displaced step buffer bytes when another thread forks
In handle_inferior_event, where we handle forks, we make sure to restore the bytes of the displaced stepping buffer in the child's address space. However, we only do it when the forking thread was the one doing a displaced step. It could happen that a thread forks while another one is doing a displaced step. In this case, we also need to restore the bytes in the child. Move the byte-restoring code outside of the condition that checks whether the event thread was displaced stepping. gdb/ChangeLog: * infrun.c (handle_inferior_event): Restore displaced step buffer bytes in child process when handling fork, even if fork happened in another thread than the displaced-stepping one. Change-Id: Ibb0daaeb123aba03f4fb4b4d820754eb2436bc69
-rw-r--r--gdb/ChangeLog6
-rw-r--r--gdb/infrun.c28
2 files changed, 21 insertions, 13 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 8ce239f..f977321 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,9 @@
+2020-12-04 Simon Marchi <simon.marchi@polymtl.ca>
+
+ * infrun.c (handle_inferior_event): Restore displaced step
+ buffer bytes in child process when handling fork, even if fork
+ happened in another thread than the displaced-stepping one.
+
2020-12-04 Simon Marchi <simon.marchi@efficios.com>
* infrun.c (infrun_inferior_execd): New function.
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 0e0a7a6..5c383b4 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -5302,25 +5302,27 @@ handle_inferior_event (struct execution_control_state *ecs)
{
struct regcache *regcache = get_thread_regcache (ecs->event_thread);
struct gdbarch *gdbarch = regcache->arch ();
+ inferior *parent_inf = find_inferior_ptid (ecs->target, ecs->ptid);
- /* If checking displaced stepping is supported, and thread
- ecs->ptid is displaced stepping. */
+ /* If this is a fork (child gets its own address space copy) and the
+ displaced step buffer was in use at the time of the fork, restore
+ displaced step buffer bytes in the child process. */
+ if (ecs->ws.kind == TARGET_WAITKIND_FORKED)
+ {
+ displaced_step_inferior_state *displaced
+ = get_displaced_stepping_state (parent_inf);
+
+ if (displaced->step_thread != nullptr)
+ displaced_step_restore (displaced, ecs->ws.value.related_pid);
+ }
+
+ /* If displaced stepping is supported, and thread ecs->ptid is
+ displaced stepping. */
if (displaced_step_in_progress_thread (ecs->event_thread))
{
- struct inferior *parent_inf
- = find_inferior_ptid (ecs->target, ecs->ptid);
struct regcache *child_regcache;
CORE_ADDR parent_pc;
- if (ecs->ws.kind == TARGET_WAITKIND_FORKED)
- {
- struct displaced_step_inferior_state *displaced
- = get_displaced_stepping_state (parent_inf);
-
- /* Restore scratch pad for child process. */
- displaced_step_restore (displaced, ecs->ws.value.related_pid);
- }
-
/* GDB has got TARGET_WAITKIND_FORKED or TARGET_WAITKIND_VFORKED,
indicating that the displaced stepping of syscall instruction
has been done. Perform cleanup for parent process here. Note