old-cross-binutils/gdb/testsuite/gdb.arch
Pedro Alves af48d08f97 fix skipping permanent breakpoints
The gdb.arch/i386-bp_permanent.exp test is currently failing an
assertion recently added:

 (gdb) stepi
 ../../src/gdb/infrun.c:2237: internal-error: resume: Assertion `sig != GDB_SIGNAL_0' failed.
 A problem internal to GDB has been detected,
 further debugging may prove unreliable.
 Quit this debugging session? (y or n)
 FAIL: gdb.arch/i386-bp_permanent.exp: Single stepping past permanent breakpoint. (GDB internal error)

The assertion expects that the only reason we currently need to step a
breakpoint instruction is when we have a signal to deliver.  But when
stepping a permanent breakpoint (with or without a signal) we also
reach this code.

The assertion is correct and the permanent breakpoints skipping code
is wrong.

Consider the case of the user doing "step/stepi" when stopped at a
permanent breakpoint.  GDB's `resume' calls the
gdbarch_skip_permanent_breakpoint hook and then happily continues
stepping:

  /* Normally, by the time we reach `resume', the breakpoints are either
     removed or inserted, as appropriate.  The exception is if we're sitting
     at a permanent breakpoint; we need to step over it, but permanent
     breakpoints can't be removed.  So we have to test for it here.  */
  if (breakpoint_here_p (aspace, pc) == permanent_breakpoint_here)
    {
      gdbarch_skip_permanent_breakpoint (gdbarch, regcache);
    }

But since gdbarch_skip_permanent_breakpoint already advanced the PC
manually, this ends up executing the instruction that is _after_ the
breakpoint instruction.  The user-visible result is that a single-step
steps two instructions.

The gdb.arch/i386-bp_permanent.exp test is actually ensuring that
that's indeed how things work.  It runs to an int3 instruction, does
"stepi", and checks that "leave" was executed with that "stepi".  Like
this:

 (gdb) b *0x0804848c
 Breakpoint 2 at 0x804848c
 (gdb) c
 Continuing.

 Breakpoint 2, 0x0804848c in standard ()
 (gdb) disassemble
 Dump of assembler code for function standard:
    0x08048488 <+0>:     push   %ebp
    0x08048489 <+1>:     mov    %esp,%ebp
    0x0804848b <+3>:     push   %edi
 => 0x0804848c <+4>:     int3
    0x0804848d <+5>:     leave
    0x0804848e <+6>:     ret
    0x0804848f <+7>:     nop
 (gdb) si
 0x0804848e in standard ()
 (gdb) disassemble
 Dump of assembler code for function standard:
    0x08048488 <+0>:     push   %ebp
    0x08048489 <+1>:     mov    %esp,%ebp
    0x0804848b <+3>:     push   %edi
    0x0804848c <+4>:     int3
    0x0804848d <+5>:     leave
 => 0x0804848e <+6>:     ret
    0x0804848f <+7>:     nop
 End of assembler dump.
 (gdb)

One would instead expect that a stepi at 0x0804848c stops at
0x0804848d, _before_ the "leave" is executed.  This commit changes GDB
this way.  Care is taken to make stepping into a signal handler when
the step starts at a permanent breakpoint instruction work correctly.

The patch adjusts gdb.arch/i386-bp_permanent.exp in this direction,
and also makes it work on x86_64 (currently it only works on i*86).

The patch also adds a new gdb.base/bp-permanent.exp test that
exercises many different code paths related to stepping permanent
breakpoints, including the stepping with signals cases.  The test uses
"hack/trick" to make it work on all (or most) platforms -- it doesn't
really hard code a breakpoint instruction.

Tested on x86_64 Fedora 20, native and gdbserver.

gdb/
2014-11-12  Pedro Alves  <palves@redhat.com>

	* infrun.c (resume): Clear the thread's 'stepped_breakpoint' flag.
	Rewrite stepping over a permanent breakpoint.
	(thread_still_needs_step_over, proceed): Don't set
	stepping_over_breakpoint for permanent breakpoints.
	(handle_signal_stop): Don't clear stepped_breakpoint.  Also pull
	single-step breakpoints out of the target on hardware step
	targets.
	(process_event_stop_test): If stepping a permanent breakpoint
	doesn't hit the step-resume breakpoint, delete the step-resume
	breakpoint.
	(switch_back_to_stepped_thread): Also check if the stepped thread
	has advanced already on hardware step targets.
	(currently_stepping): Return true if the thread stepped a
	breakpoint.

gdb/testsuite/
2014-11-12  Pedro Alves  <palves@redhat.com>

	* gdb.arch/i386-bp_permanent.c: New file.
	* gdb.arch/i386-bp_permanent.exp: Don't skip on x86_64.
	(srcfile): Set to i386-bp_permanent.c.
	(top level): Adjust to work in both 32-bit and 64-bit modes.  Test
	that stepi does not execute the 'leave' instruction, instead of
	testing it does execute.
	* gdb.base/bp-permanent.c: New file.
	* gdb.base/bp-permanent.exp: New file.
2014-11-12 10:39:00 +00:00
..
aarch64-atomic-inst.c
aarch64-atomic-inst.exp
alpha-step.c
alpha-step.exp
altivec-abi.c
altivec-abi.exp
altivec-regs.c
altivec-regs.exp
amd64-byte.exp
amd64-disp-step.exp
amd64-disp-step.S
amd64-dword.exp
amd64-entry-value-inline.c
amd64-entry-value-inline.exp
amd64-entry-value-inline.S
amd64-entry-value-param.c
amd64-entry-value-param.exp
amd64-entry-value-param.S
amd64-entry-value-paramref.cc
amd64-entry-value-paramref.exp
amd64-entry-value-paramref.S
amd64-entry-value.cc
amd64-entry-value.exp
amd64-entry-value.s
amd64-i386-address.exp
amd64-i386-address.S
amd64-invalid-stack-middle.c
amd64-invalid-stack-middle.exp
amd64-invalid-stack-middle.S
amd64-invalid-stack-top.c
amd64-invalid-stack-top.exp
amd64-optimout-repeat.c
amd64-optimout-repeat.exp
amd64-optimout-repeat.S
amd64-prologue-xmm.c
amd64-prologue-xmm.exp
amd64-prologue-xmm.s
amd64-pseudo.c
amd64-stap-optional-prefix.exp
amd64-stap-optional-prefix.S
amd64-stap-special-operands.exp
amd64-stap-three-arg-disp.c
amd64-stap-three-arg-disp.S
amd64-stap-triplet.c
amd64-stap-triplet.S
amd64-stap-wrong-subexp.exp
amd64-stap-wrong-subexp.S
amd64-tailcall-cxx.exp
amd64-tailcall-cxx1.cc
amd64-tailcall-cxx1.S
amd64-tailcall-cxx2.cc
amd64-tailcall-cxx2.S
amd64-tailcall-noret.c
amd64-tailcall-noret.exp
amd64-tailcall-noret.S
amd64-tailcall-ret.c
amd64-tailcall-ret.exp
amd64-tailcall-ret.S
amd64-word.exp
arm-bl-branch-dest.c
arm-bl-branch-dest.exp
arm-disp-step.exp
arm-disp-step.S
avr-flash-qualifier.c
avr-flash-qualifier.exp
e500-abi.c
e500-abi.exp
e500-prologue.c
e500-prologue.exp
e500-regs.c
e500-regs.exp
gdb1291.exp
gdb1291.s
gdb1431.exp
gdb1431.s
gdb1558.c
gdb1558.exp
i386-avx.c
i386-avx.exp
i386-avx512.c
i386-avx512.exp
i386-bp_permanent.c
i386-bp_permanent.exp
i386-byte.exp
i386-cfi-notcurrent.exp
i386-cfi-notcurrent.S
i386-disp-step.exp
i386-disp-step.S
i386-dr3-watch.c
i386-dr3-watch.exp
i386-float.exp
i386-float.S
i386-gnu-cfi-asm.S
i386-gnu-cfi.c
i386-gnu-cfi.exp
i386-mpx.c
i386-mpx.exp
i386-permbkpt.exp
i386-permbkpt.S
i386-prologue.c
i386-prologue.exp
i386-pseudo.c
i386-signal.c
i386-signal.exp
i386-size-overlap.c
i386-size-overlap.exp
i386-size.c
i386-size.exp
i386-sse-stack-align.c
i386-sse-stack-align.exp
i386-sse-stack-align.S
i386-sse.c
i386-sse.exp
i386-stap-eval-lang-ada.c
i386-stap-eval-lang-ada.exp
i386-stap-eval-lang-ada.S
i386-unwind.c
i386-unwind.exp
i386-word.exp
ia64-breakpoint-shadow.exp
ia64-breakpoint-shadow.S
iwmmxt-regs.c
iwmmxt-regs.exp
Makefile.in
mips-octeon-bbit.c
mips-octeon-bbit.exp
mips16-thunks-inmain.c
mips16-thunks-main.c
mips16-thunks-sin.c
mips16-thunks-sinfrob.c
mips16-thunks-sinfrob16.c
mips16-thunks-sinmain.c
mips16-thunks-sinmips16.c
mips16-thunks.exp
pa-nullify.exp
pa-nullify.s
pa64-nullify.s
powerpc-aix-prologue.c
powerpc-aix-prologue.exp
powerpc-d128-regs.c
powerpc-d128-regs.exp
powerpc-power.exp
powerpc-power.s
powerpc-prologue.c
powerpc-prologue.exp
powerpc-stackless.exp
powerpc-stackless.S
ppc-dfp.c
ppc-dfp.exp
ppc-fp.c
ppc-fp.exp
ppc64-atomic-inst.exp
ppc64-atomic-inst.S
s390-multiarch.c
s390-multiarch.exp
s390-tdbregs.c
s390-tdbregs.exp
sparc-sysstep.c
sparc-sysstep.exp
spu-info.c
spu-info.exp
spu-ls.c
spu-ls.exp
thumb-bx-pc.exp
thumb-bx-pc.S
thumb-prologue.c
thumb-prologue.exp
thumb-singlestep.exp
thumb-singlestep.S
thumb2-it.exp
thumb2-it.S
vsx-regs.c
vsx-regs.exp