Unneeded displaced single stepping causes issues: Performance drop and range stepping killer

Yao Qi yao@codesourcery.com
Wed Apr 24 02:24:00 GMT 2013

On 04/22/2013 06:54 PM, Raphael Zulliger wrote:
> Hi
> I've been playing around with the 'range stepping' patch set. (Thanks
> for that great feature!) Thereby I encountered the following behavior:

Thanks for playing with range stepping!

>       Targets, having a 'gdbarch->software_single_step' function set, are
> always using displaced single stepping even when "normal" single
> stepping would be sufficient. (sure, displaced single-stepping may have
> the advantage of less breakpoint hits by foreign task, but...)
> While this is not a problem as such, it may be sub-optimal because:
>       Issue a) At least on extended-remote ppc target displaced single
> stepping causes much more RSP traffic
>       Issue b) It renders 'range stepping' useless
> Let me explain Issue a)
> Not sure whether this statement is correct for all platform out there,
> but on my PPC603/EABI extended remote target, the difference between
> non- vs. displaced single stepping is quite big.
>           (gdb) set displaced-stepping 0
>           (gdb) si
>           Sending packet: $m832d0,4#fe...Packet received: 9421ffc8
>           Sending packet: $vCont;s:p1.dca118#83...Packet received: OK
>             Notification received:
> Stop:T05thread:p1.dca118;0:00dcdea0;1:00dcde40;2:00dca118;3:00dcdea4;4:00dcdea0;5:00000142;6:00dcde68;7:00000002;8:00000005;9:00dcdea4;a:00579e90;b:00ed4b34;c:00000000;d:f7ffffff;e:00000357;f:f1010000;10:00000000;11:fff71658;12:0068e738;13:001dd964;14:00000000;15:00000000;16:0069c120;17:00000000;18:00000037;19:00000000;1a:00000032;1b:00e6b2c0;1c:00087e48;1d:00ed12a0;1e:00ed1b68;1f:00dcde78;20:00000006347fd013;21:3ff199999999999a;22:3ff199999999999a;23:0000000000000000;24:0000000000000000;25:0000000000000000;26:0000000000000000;27:0000000000000000;28:0000000000000000;29:0000000000000000;2a:0000000000000000;2b:0000000000000000;2c:401900a3d70a3d71;2d:3ff199999999999a;2e:0000000000000000;2f:0000000000000000;30:0000000000000000;31:0000000000000000;32:0000000000000000;33:0000000000000000;34:0000000000000000;35:0000000000000000;36:0000000000000000;37:0000000000000000;38:0000000000000000;39:0000000000000000;3a:0000000000000000;3b:0000000000000000;3c:0000000000000000;3d:0000000000000000;3e:0
>           Sending packet: $vStopped#55...Packet received: OK
>           0x000832d4    20    SourceLine::SourceLine( const std::string
> &fileName,
> versus:
>           (gdb) set displaced-stepping 1
>           (gdb) si
>           Sending packet: $m1508,4#9b...Packet received: 3c000058
>           Sending packet: $m832d4,4#02...Packet received: 7c0802a6
>           Sending packet: $X1508,0:#bc...Packet received:
>           binary downloading NOT supported by target
>           Sending packet: $M1508,4:7c0802a6#b0...Packet received: OK
>           Sending packet: $g#67...Packet received:
> 00dcdea000dcde4000dca11800dcdea400dcdea00000014200dcde68000000020000000500dcdea400579e9000ed4b3400000000f7ffffff00000357f101000000000000fff716580068e738001dd96400000000000000000069c1200000000000000037000000000000003200e6b2c000087e4800ed12a000ed1b6800dcde7800000006347fd0133ff199999999999a3ff199999999999a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000401900a3d70a3d713ff199999999999a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000832d40008a0302000000400049cd00000000000000000efbeadde
>           Sending packet: $P40=00001508#7f...Packet received: OK
>           Packet P (set-register) is supported
>           Sending packet: $vCont;s:p1.dca118#83...Packet received: OK
>             Notification received:
> Stop:T05thread:p1.dca118;0:00049cd0;1:00dcde40;2:00dca118;3:00dcdea4;4:00dcdea0;5:00000142;6:00dcde68;7:00000002;8:00000005;9:00dcdea4;a:00579e90;b:00ed4b34;c:00000000;d:f7ffffff;e:00000357;f:f1010000;10:00000000;11:fff71658;12:0068e738;13:001dd964;14:00000000;15:00000000;16:0069c120;17:00000000;18:00000037;19:00000000;1a:00000032;1b:00e6b2c0;1c:00087e48;1d:00ed12a0;1e:00ed1b68;1f:00dcde78;20:00000006347fd013;21:3ff199999999999a;22:3ff199999999999a;23:0000000000000000;24:0000000000000000;25:0000000000000000;26:0000000000000000;27:0000000000000000;28:0000000000000000;29:0000000000000000;2a:0000000000000000;2b:0000000000000000;2c:401900a3d70a3d71;2d:3ff199999999999a;2e:0000000000000000;2f:0000000000000000;30:0000000000000000;31:0000000000000000;32:0000000000000000;33:0000000000000000;34:0000000000000000;35:0000000000000000;36:0000000000000000;37:0000000000000000;38:0000000000000000;39:0000000000000000;3a:0000000000000000;3b:0000000000000000;3c:0000000000000000;3d:0000000000000000;3e:0
>           Sending packet: $vStopped#55...Packet received: OK
>           Sending packet: $M1508,4:3c000058#78...Packet received: OK
>           Sending packet: $P40=000832d8#ba...Packet received: OK
>           0x000832d8    20    SourceLine::SourceLine( const std::string
> &fileName,
>           (gdb)

Without displaced stepping, when GDB steps over breakpoint for one
thread, other threads will be affected.  With displaced stepping, when
GDB steps over breakppoint, other threads won't be affected, but as you
say, there are more RSP traffic.  We need to balance on thread-stop
delay vs. rsp traffic delay.  Probably, you can try to disable
displaced stepping, to see if it helps to speed up.

> Issue b)
> According to my current understanding (please correct me if I'm wrong):
> Range stepping decides whether to send a 'vCont;r' package by comparing
> the current program counter with the range that needs to be executed
> (control.step_range_start and control.step_range_end). Using displaced

Yes, you are right.

> single stepping means that the program counter is, by definition, always
> outside the range that needs to be single stepped and thus 'range
> stepping' will never be used.

Once GDB decides to do displaced stepping, it will place equivalent
instructions at scratch pad to emulate the original instruction,
resumes inferior from scratch pad, and expects the stop.  That means
GDB is aware of every stop after the execution of each instruction, so
range stepping can't be used.  The rationale of range stepping is that,
GDB tells the remote stub to do single in a range of address, and
report a stop once PC is out of the range, in order to reduce the rsp
traffic.  During the range stepping, GDB is not aware of how many stops
occurred in the range.

> What causes the problem?
> The following statement (from infrun.c, resume(), git master) decides
> whether to use displaced single stepping or not:
>     if (use_displaced_stepping (gdbarch)
>         && (tp->control.trap_expected
>         || (step && gdbarch_software_single_step_p (gdbarch)))
>         && sig == GDB_SIGNAL_0
>         && !current_inferior ()->waiting_for_vfork_done)
> According to my experiments:
>       - Using gdb/gdbserver on x86/64, that statement is 'true' when we
> step over a breakpoint, but is 'false' otherwise ->range stepping is
> used when possible
>       - Using extended remote to ppc603/EABI embedded system, that
> statement is always 'true' when we step because
> 'gdbarch_software_single_step_p' returns 'true' ->range stepping is
> never used

Once GDB decides to do software single step, it will insert a software
single step breakpoint at the next instruction of PC, resume inferior,
and expect a stop on that address.  This will cause a lot of RSP
traffic, which can't be reduced.  Then, range stepping is useless.

>       - When patching GDB so that 'gdbarch->software_single_step = NULL',
> then the behavior is like on x86/64 and thus 'range stepping' works
> ->range stepping is used when possible
> Finally, my request: Could someone with more insight into GDB internals
> please decide whether we have to fix something here and if yes, how? Or,
> in case that my conclusions are wrong, could you help me to really
> understand the problem? (FYI: My ultimate goal is to speedup remote
> debugging for our ppc603/EABI target.)

Considering your goal, I suggest that please make range stepping on,
and probably turn displaced stepping off.  If you are using breakpoint
with conditions, please 'set breakpoint condition-evaluation target'
(it requires your remote stub support condition evaluation), it will
improve the performance to some extent.

On the other hand, we have a local patch to prefer range stepping to
software single step:

diff --git a/gdb/infrun.c b/gdb/infrun.c
index cbc11f7..b606384 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -1824,7 +1824,9 @@ a command like `return' or `jump' to continue execution."));
   /* Do we need to do it the hard way, w/temp breakpoints?  */
-  else if (step)
+  else if (step
+	   && !(target supports range stepping () /* undefined */
     step = maybe_software_singlestep (gdbarch, pc);
   /* Currently, our software single-step implementation leads to different

target_supports_range_stepping can be hacked to 1 in your case.  It
helps in your case that the remote stub is able to do single step
while the GDB side uses software single step.

My range stepping series didn't include this patch above, because it is a
step-2" patch series.  My plan is to draft and post the "step-2"
patches series after getting some comments on range stepping patches.
I'd like to get the existing patches reviewed and committed first, and the
start to work on "step-2" patches.

B.T.W, we are looking for the opportunities to improve the performance
of remote debugging, "target-side condition evaluation" and
"range stepping" are of this kind.  If you know some cases are extremely
slow, please let us know.

Yao (齐尧)

More information about the Gdb mailing list