[PATCH,ARM] Fix single step on vfork

Yao Qi
2010-09-01T16:56:54Z

[-- Attachment #1: Type: text/plain, Size: 719 bytes --]

Hi,
Recently, we find some failures in gdb testsute on ARM,

FAIL: gdb.base/watch-vfork.exp: Watchpoint triggers after vfork (hw)
(the program exited)
FAIL: gdb.base/watch-vfork.exp: Watchpoint triggers after vfork (sw)
(the program exited)

Program exits when we stepping over svc instruction in vfork(), which is
caused by child process hits software single step breakpoint inserted
for parent process.

This patch is to fix this problem by 'when inferior's
wait_for_vfork_done is true, clear step to zero and don't use displaced
stepping'.

Tested on GDB CVS on ARM and X86-64. Fix these two failures above on
ARM, and no regressions. OK to apply?

--
Yao Qi
CodeSourcery
yao@codesourcery.com
(650) 331-3385 x739

[-- Attachment #2: single_step_vfork_1.patch --]
[-- Type: text/x-patch, Size: 1858 bytes --]

2010-09-02 Yao Qi <yao@codesourcery.com>

* infrunc(resume): When inferior is waiting_for_vfork_done,
clear step and don't use displaced stepping.

diff --git a/gdb/infrun.c b/gdb/infrun.c
index dd89e78..2f28380 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -1550,6 +1550,19 @@ resume (int step, enum target_signal sig)

QUIT;

+ /* Don't consider single-stepping when the inferior is
+ waiting_for_vfork_done, either software or hardware step. In
+ software step, child process will hit the software single step
+ breakpoint inserted in parent process. In hardware step, GDB
+ can resumes inferior, and waiting for vfork_done event. */
+ if (current_inferior()->waiting_for_vfork_done)
+ {
+ if (debug_infrun)
+ fprintf_unfiltered (gdb_stdlog,
+ "infrun: resume : clear step\n");
+ step = 0;
+ }
+
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog,
"infrun: resume (step=%d, signal=%d), "
@@ -1577,11 +1590,16 @@ a command like `return' or `jump' to continue execution."));
We can't use displaced stepping when we have a signal to deliver;
the comments for displaced_step_prepare explain why. The
comments in the handle_inferior event for dealing with 'random
- signals' explain what we do instead. */
+ signals' explain what we do instead.
+
+ We can't use displaced stepping when we are waiting for vfork_done
+ event, displaced stepping breaks the vfork child similarly as single
+ step software breakpoint. */
if (use_displaced_stepping (gdbarch)
&& (tp->trap_expected
|| (step && gdbarch_software_single_step_p (gdbarch)))
- && sig == TARGET_SIGNAL_0)
+ && sig == TARGET_SIGNAL_0
+ && !current_inferior()->waiting_for_vfork_done)
{
struct displaced_step_inferior_state *displaced;