Using and understanding the Valgrind core: Advanced Topics
• Connecting to or interrupting a Valgrind process blocked in a system call.
Connecting to or interrupting a Valgrind process blocked in a system call requires the "ptrace" system call to be
usable. This may be disabled in your kernel for security reasons.
When running your program, Valgrind’s scheduler periodically checks whether there is any work to be handled by
the gdbserver.
Unfortunately this check is only done if at least one thread of the process is runnable.
If all the
threads of the process are blocked in a system call, then the checks do not happen, and the Valgrind scheduler will
not invoke the gdbserver. In such a case, the vgdb relay application will "force" the gdbserver to be invoked, without
the intervention of the Valgrind scheduler.
Such forced invocation of the Valgrind gdbserver is implemented by vgdb using ptrace system calls. On a properly
implemented kernel, the ptrace calls done by vgdb will not influence the behaviour of the program running under
Valgrind. If however they do, giving the option
--max-invoke-ms=0
to the vgdb relay application will disable
the usage of ptrace calls. The consequence of disabling ptrace usage in vgdb is that a Valgrind process blocked in
a system call cannot be woken up or interrupted from GDB until it executes enough basic blocks to let the Valgrind
scheduler’s normal checking take effect.
When ptrace is disabled in vgdb, you can increase the responsiveness of the Valgrind gdbserver to commands or
interrupts by giving a lower value to the option
--vgdb-poll
.
If your application is blocked in system calls
most of the time, using a very low value for
--vgdb-poll
will cause a the gdbserver to be invoked sooner. The
gdbserver polling done by Valgrind’s scheduler is very efficient, so the increased polling frequency should not cause
significant performance degradation.
When ptrace is disabled in vgdb, a query packet sent by GDB may take significant time to be handled by the Valgrind
gdbserver. In such cases, GDB might encounter a protocol timeout. To avoid this, you can increase the value of
the timeout by using the GDB command "set remotetimeout".
Ubuntu versions 10.10 and later may restrict the scope of ptrace to the children of the process calling ptrace. As the
Valgrind process is not a child of vgdb, such restricted scoping causes the ptrace calls to fail. To avoid that, when
Valgrind gdbserver receives the first packet from a vgdb, it calls
prctl(PR_SET_PTRACER, vgdb_pid, 0,
0, 0)
to ensure vgdb can reliably use ptrace. Once
vgdb_pid
has been marked as a ptracer, vgdb can then
properly force the invocation of Valgrind gdbserver when needed. To ensure the vgdb is set as a ptracer before the
Valgrind process gets blocked in a system call, connect your GDB to the Valgrind gdbserver at startup by passing
--vgdb-error=0
to Valgrind.
Note that this "set ptracer" technique does not solve the problem in the case where a standalone vgdb process wants
to connect to the gdbserver, since the first command to be sent by a standalone vgdb must wake up the Valgrind
process before Valgrind gdbserver will mark vgdb as a ptracer.
Unblocking processes blocked in system calls is not currently implemented on Mac OS X and Android.
So you
cannot connect to or interrupt a process blocked in a system call on Mac OS X or Android.
• Changing register values.
The Valgrind gdbserver will only modify the values of the thread’s registers when the thread is in status Runnable
or Yielding. In other states (typically, WaitSys), attempts to change register values will fail. Amongst other things,
this means that inferior calls are not executed for a thread which is in a system call, since the Valgrind gdbserver
does not implement system call restart.
• Unsupported GDB functionality.
GDB provides a lot of debugging functionality and not all of it is supported.
Specifically, the following are not
supported: reversible debugging and tracepoints.
41