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

Pedro Alves palves@redhat.com
Tue Apr 23 19:03:00 GMT 2013

On 04/22/2013 11:54 AM, Raphael Zulliger wrote:

> 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 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.

I've been hacking on the range stepping series, and I've actually
changed how GDB decides to issue a range-step or not.
By "PC-is-in-range" has problems.  But, that's largely unrelated.
The root issue is the forced displaced step, and that'll remain
the same.

> 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
>     - 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.)

There are several things to consider here.  The
"(step && gdbarch_software_single_step_p (gdbarch))" part
was added because GDB can't currently do multiple software
single-steps simultaneously, which is a problem for non-stop
mode (which enables displaced stepping).  The workaround was to force
displaced stepping for all single-steps.  GDB knows how to queue
displaced step requests (necessary because there's only one scratch
pad for all threads), and have threads wait for their turn in the
queue.  I was working on making GDB aware of multiple software
single-steps a while ago, but I got distracted with other things
and haven't finished that yet...

Then, as you note, gdbarch_software_single_step_p isn't really the
right predicate.  A better one would be "do I need to software
single-step this instruction".  There's no such predicate today,
because the gdbarch_software_single_step hook is responsible for
installing the breakpoints itself, instead of returning a vector
of the locations where breakpoints should be set (which I think
would be better).

Pedro Alves

More information about the Gdb mailing list