This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [pushed] gdbserver: redo stepping over breakpoint that was on top of a permanent breakpoint


Pedro Alves <palves@redhat.com> writes:

Hi Pedro,
when I play with Antoine's patch series,

  [PATCH 0/5] Software breakpoints support for ARM linux.
  https://sourceware.org/ml/gdb-patches/2015-09/msg00448.html

I force GDBserver to use thread event breakpoint in order to exercise
Antoine's patch series.  Something strange leads me to this patch....

> +  /* If step-over executes a breakpoint instruction, it means a
> +     gdb/gdbserver breakpoint had been planted on top of a permanent
> +     breakpoint.  The PC has been adjusted by
> +     check_stopped_by_breakpoint to point at the breakpoint address.
> +     Advance the PC manually past the breakpoint, otherwise the
> +     program would keep trapping the permanent breakpoint forever.  */
> +  if (!ptid_equal (step_over_bkpt, null_ptid)
> +      && event_child->stop_reason == LWP_STOPPED_BY_SW_BREAKPOINT)
> +    {

The code was added to handle permanent breakpoint, but the condition can
also be true when GDBserver steps over breakpoint by software single
step (through breakpoint_reinsert_addr), and the following the code
increase the PC, and as a result, one instruction is not executed, as
shown below,

> +      unsigned int increment_pc;
> +
> +      if (the_low_target.breakpoint_len > the_low_target.decr_pc_after_break)
> +	increment_pc = the_low_target.breakpoint_len;
> +      else
> +	increment_pc = the_low_target.decr_pc_after_break;
> +

the program gets SIGSEGV after calling __nptl_create_event,

Breakpoint 1, main () at /home/yao/SourceCode/gnu/gdb/git/gdb/testsuite/gdb.threads/tls.c:231
231	   do_pass ();
(gdb) c
Continuing.
[New Thread 16290]

Program received signal SIGSEGV, Segmentation fault.
0xb6fcb6d2 in create_thread (stackaddr=0xb6daff80, attr=0xbefff580, pd=0xb6db0440) at ../nptl/sysdeps/pthread/createthread.c:223
223	../nptl/sysdeps/pthread/createthread.c: No such file or directory.

(gdb) disassemble 0xb6fcb6c0,+20
Dump of assembler code from 0xb6fcb6c0 to 0xb6fcb6d4:
   0xb6fcb6c0 <__pthread_create_2_1+1160>:	ldrh	r7, [r3, #58]	; 0x3a
   0xb6fcb6c2 <__pthread_create_2_1+1162>:	bne.n	0xb6fcb6a2 <__pthread_create_2_1+1130>
   0xb6fcb6c4 <__pthread_create_2_1+1164>:	bl	0xb6fca124 <__GI___nptl_create_event>
   0xb6fcb6c8 <__pthread_create_2_1+1168>:	add.w	r0, r4, #532	; 0x214
   0xb6fcb6cc <__pthread_create_2_1+1172>:	movs	r2, #0
   0xb6fcb6ce <__pthread_create_2_1+1174>:	dmb	sy
=> 0xb6fcb6d2 <__pthread_create_2_1+1178>:	ldrex	r3, [r0]
(gdb) p __nptl_create_event 
$1 = {<text variable, no debug info>} 0xb6fca124 <__GI___nptl_create_event>

in GDBserver, we can see the debug log,

stop pc is b6fca124

  [1] program hits the GDBserver brekapoint on __nptl_create_event

pc is 0xb6fca124
Writing 7047 to 0xb6fca124 in process 16289
Could not find fast tracepoint jump at 0xb6fca124 in list (uninserting).
Writing f0f700a0 to 0xb6fcb6c8 in process 16289

  [2] GDBservers sets software breakpoint on the instruction after bl
  __nptl_create_event.

Resuming lwp 16289 (continue, signal 0, stop not expected)
  pending reinsert at 0xb6fca124
stop pc is b6fca124
  continue from pc 0xb6fca124
>>>> entering linux_wait_1
sigchld_handler
linux_wait_1: [<all threads>]
step_over_bkpt set [LWP 16289.16289], doing a blocking wait
my_waitpid (-1, 0x40000001)
my_waitpid (-1, 0x1): status(57f), 16289
LWFE: waitpid(-1, ...) returned 16289, ERRNO-OK
LLW: waitpid 16289 received Trace/breakpoint trap (stopped)
stop pc is b6fcb6c8
pc is 0xb6fcb6c8
CSBB: LWP 16289.16289 stopped by software breakpoint

  [3] program hits the single step software breakpoint,

my_waitpid (-1, 0x40000001)
my_waitpid (-1, 0x80000001): status(ffffffff), 0
LWFE: waitpid(-1, ...) returned 0, ERRNO-OK
stop pc is b6fcb6c8
pc is 0xb6fcb6c8
step-over for LWP 16289.16289 executed software breakpoint
Finished step over.
Writing 01de to 0xb6fca124 in process 16289
Could not find fast tracepoint jump at 0xb6fca124 in list (reinserting).
Writing 04f50570 to 0xb6fcb6c8 in process 16289
Step-over finished.
proceeding all threads.
Need step over [LWP 16289]? No
stop pc is b6fcb6cc
pc is 0xb6fcb6cc

  [4] pc is incremented by 4, which means instruction on 0xb6fcb6c8 is
  not executed.

I am not very sure what the right fix should be, but looks we need to
check whether there is a breakpoint installed on event_child-stop_pc,
something like this patch below, what do you think?

-- 
Yao (éå)

Subject: [PATCH] Step-over breakpoint by software single step

gdb/gdbserver:

2015-09-24  Yao Qi  <yao.qi@linaro.org>

	* linux-low.c (linux_wait_1): Call gdb_breakpoint_here.

diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index 8e8b7c0..9fb83a8 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -3010,7 +3010,8 @@ linux_wait_1 (ptid_t ptid,
      Advance the PC manually past the breakpoint, otherwise the
      program would keep trapping the permanent breakpoint forever.  */
   if (!ptid_equal (step_over_bkpt, null_ptid)
-      && event_child->stop_reason == TARGET_STOPPED_BY_SW_BREAKPOINT)
+      && event_child->stop_reason == TARGET_STOPPED_BY_SW_BREAKPOINT
+      && gdb_breakpoint_here (event_child->stop_pc))
     {
       int increment_pc = 0;
       CORE_ADDR stop_pc = event_child->stop_pc;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]