vgdb: implement the extended-remote protocol

Executing vgdb --multi makes vgdb talk the gdb extended-remote
protocol. This means that the gdb run command is supported and
vgdb will start up the program under valgrind. Which means you
don't need to run gdb and valgrind from different terminals.
Also vgdb keeps being connected to gdb after valgrind exits. So
you can easily rerun the program with the same breakpoints in
place.

vgdb now implements a minimal gdbserver that just recognizes
a few extended-remote protocol packets. Once it starts up valgrind
it sets up noack and qsupported then it will forward packets
between gdb and valgrind gdbserver. After valgrind shutsdown it
resumes handling gdb packets itself.

https://bugs.kde.org/show_bug.cgi?id=434057

Co-authored-by: Mark Wielaard <mark@klomp.org>
This commit is contained in:
Alexandra Petlanova Hajkova
2022-03-03 04:46:03 -05:00
committed by Mark Wielaard
parent 0ae17c117e
commit 0432ce486d
11 changed files with 914 additions and 27 deletions

12
NEWS
View File

@@ -34,6 +34,17 @@ AMD64/macOS 10.13 and nanoMIPS/Linux.
$3 = 40
(gdb) monitor who_point_at 0x1130a0 40
* The vgdb utility now supports extended-remote protocol when
invoked with --multi. In this mode the GDB run command is
supported. Which means you don't need to run gdb and valgrind
from different terminals. So for example to start you program
in gdb and run it under valgrind you can do:
$ gdb prog
(gdb) set remote exec-file prog
(gdb) set sysroot /
(gdb) target extended-remote | vgdb --multi
(gdb) start
* The behaviour of realloc with a size of zero can now
be changed for tools that intercept malloc. Those
tools are memcheck, helgrind, drd, massif and dhat.
@@ -116,6 +127,7 @@ are not entered into bugzilla tend to get forgotten about or ignored.
392331 Spurious lock not held error from inside pthread_cond_timedwait
400793 pthread_rwlock_timedwrlock false positive
433873 openat2 syscall unimplemented on Linux
434057 Add stdio mode to valgrind's gdbserver
435441 valgrind fails to interpose malloc on musl 1.2.2 due to weak symbol name and no libc soname
444110 priv/guest_ppc_toIR.c:36198:31: warning: duplicated 'if' condition.
444488 Use glibc.pthread.stack_cache_size tunable

View File

@@ -29,7 +29,7 @@
<title>Description</title>
<para><command>vgdb</command> ("Valgrind to GDB") is used as an
intermediary between Valgrind and GDB or a shell. It has two usage modes:
intermediary between Valgrind and GDB or a shell. It has three usage modes:
</para>
<xi:include href="../../docs/xml/manual-core-adv.xml"

View File

@@ -601,8 +601,9 @@ void VG_(gdbserver_prerun_action) (ThreadId tid)
{
// Using VG_(clo_vgdb_error) allows the user to control if gdbserver
// stops after a fork.
if (VG_(clo_vgdb_error) == 0
|| VgdbStopAtiS(VgdbStopAt_Startup, VG_(clo_vgdb_stop_at))) {
if ((VG_(clo_vgdb_error) == 0
|| (VgdbStopAtiS(VgdbStopAt_Startup, VG_(clo_vgdb_stop_at))))
&& !(VG_(clo_launched_with_multi))) {
/* The below call allows gdb to attach at startup
before the first guest instruction is executed. */
VG_(umsg)("(action at startup) vgdb me ... \n");

View File

@@ -372,8 +372,9 @@ void remote_open (const HChar *name)
pid);
}
if (VG_(clo_verbosity) > 1
|| VG_(clo_vgdb_error) < 999999999
|| VG_(clo_vgdb_stop_at) != 0) {
|| ((VG_(clo_vgdb_error) < 999999999
|| VG_(clo_vgdb_stop_at) != 0)
&& !(VG_(clo_launched_with_multi)))) {
VG_(umsg)("\n");
VG_(umsg)(
"TO DEBUG THIS PROCESS USING GDB: start GDB like this\n"

View File

@@ -843,6 +843,7 @@ void handle_query (char *arg_own_buf, int *new_packet_len_p)
}
}
/* Without argument, traditional remote protocol. */
if (strcmp ("qAttached", arg_own_buf) == 0) {
/* tell gdb to always detach, never kill the process */
arg_own_buf[0] = '1';
@@ -850,6 +851,14 @@ void handle_query (char *arg_own_buf, int *new_packet_len_p)
return;
}
/* With argument, extended-remote protocol. */
if (strncmp ("qAttached:", arg_own_buf, strlen ("qAttached:")) == 0) {
/* We just created this process */
arg_own_buf[0] = '0';
arg_own_buf[1] = 0;
return;
}
if (strcmp ("qSymbol::", arg_own_buf) == 0) {
/* We have no symbol to read. */
write_ok (arg_own_buf);

View File

@@ -279,6 +279,7 @@ static void usage_NORETURN ( int need_help )
" --progress-interval=<number> report progress every <number>\n"
" CPU seconds [0, meaning disabled]\n"
" --command-line-only=no|yes only use command line options [no]\n"
" --launched-with-multi=no|yes valgrind launched in vgdb multi mode [no]\n"
"\n"
" Vex options for all Valgrind tools:\n"
" --vex-iropt-verbosity=<0..9> [0]\n"
@@ -562,6 +563,8 @@ static void process_option (Clo_Mode mode,
}
else if VG_INT_CLOM (cloPD, arg, "--vgdb-poll", VG_(clo_vgdb_poll)) {}
else if VG_INT_CLOM (cloPD, arg, "--vgdb-error", VG_(clo_vgdb_error)) {}
else if VG_BOOL_CLO (arg, "--launched-with-multi",
VG_(clo_launched_with_multi)) {}
else if VG_USET_CLOM (cloPD, arg, "--vgdb-stop-at",
"startup,exit,abexit,valgrindabexit",
VG_(clo_vgdb_stop_at)) {}

View File

@@ -106,6 +106,7 @@ VgVgdb VG_(clo_vgdb) = Vg_VgdbYes;
#endif
Int VG_(clo_vgdb_poll) = 5000;
Int VG_(clo_vgdb_error) = 999999999;
Bool VG_(clo_launched_with_multi) = False;
UInt VG_(clo_vgdb_stop_at) = 0;
const HChar *VG_(clo_vgdb_prefix) = NULL;
const HChar *VG_(arg_vgdb_prefix) = NULL;

File diff suppressed because it is too large Load Diff

View File

@@ -482,6 +482,29 @@ Loaded symbols for /lib/ld-linux.so.2
(gdb)
]]></programlisting>
<para>If you want to use the <option>--multi</option> mode which makes vgdb start in extended-remote mode, set the following in GDB:
<screen><![CDATA[
# gdb prog
(gdb) set remote exec-file prog
(gdb) set sysroot /
(gdb) target extended-remote | vgdb --multi --vargs -q
(gdb) start
Temporary breakpoint 1 at 0x24e0
Starting program: prog
relaying data between gdb and process 2999348
Temporary breakpoint 1, 0x000000000010a4a0 in main ()
(gdb)
]]></screen>
</para>
<para>Note that in <option>--multi</option> mode you don't have to
start valgrind separately. vgdb will start valgrind for
you. vgdb <option>--multi</option> mode is experimental and currently
has some limitations like not being able to see program stdin and
stdout. Also you have to explicitly set the remote exec-file and
sysroot to tell GDB the "remote" and local files are the same.</para>
<para>Once GDB is connected to the Valgrind gdbserver, it can be used
in the same way as if you were debugging the program natively:</para>
<itemizedlist>
@@ -1254,7 +1277,7 @@ $5 = 36
<para> vgdb ("Valgrind to GDB") is a small program that is used as an
intermediary between Valgrind and GDB or a shell.
Therefore, it has two usage modes:
It has three usage modes:
</para>
<!-- start of xi:include in the manpage -->
<orderedlist id="vgdb.desc.modes">
@@ -1275,6 +1298,19 @@ Therefore, it has two usage modes:
</para>
</listitem>
<listitem id="manual-core-adv.vgdb-multi" xreflabel="vgdb multi">
<para>In the <option>--multi</option> mode, Vgdb uses the extended
remote protocol to communicate with Gdb. This allows you to view
output from both valgrind and GDB in the GDB session. This is
accomplished via the "target extended-remote | vgdb --multi". In
this mode you no longer need to start valgrind yourself. vgdb will
start up valgrind when gdb tells it to run a new program. For this
usage, the vgdb OPTIONS(s) can also include <option>--valgrind</option>
and <option>--vargs</option> to describe how valgrind should be
started.
</para>
</listitem>
</orderedlist>
<!-- end of xi:include in the manpage -->
@@ -1369,7 +1405,28 @@ gdb prog
where targetip is the ip address or hostname of the target computer.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--vgdb-multi</option></term>
<listitem><para>Makes vgdb start in extended-remote mode and to wait
for gdb to tell us what to run.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--valgrind</option></term>
<listitem><para>The path to valgrind to use, in extended-remote
mode. If not specified, the system valgrind will be
launched.</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--vargs</option></term>
<listitem><para>Options to run valgrind with, in extended-remote
mode. For example <option>-q</option>. Everything
following <option>--vargs</option> will be provided as arguments
to valgrind as is. </para></listitem>
</varlistentry>
<varlistentry>
<term><option>-c</option></term>
<listitem><para>To give more than one command to a

View File

@@ -332,6 +332,11 @@ extern Bool VG_(clo_stats);
Note that this value can be changed dynamically. */
extern Int VG_(clo_vgdb_error);
/* Set by vgdb in --multi mode when launching valgrind. This suppresses
the "TO DEBUG" banner because vgdb will take care of attaching in that
case. */
extern Bool VG_(clo_launched_with_multi);
/* If user has provided the --vgdb-prefix command line option,
VG_(arg_vgdb_prefix) points at the provided argument (including the
'--vgdb-prefix=' string).

View File

@@ -28,5 +28,5 @@ vgbasedir=`dirname $scriptname`
# 'inner' builds.
VALGRIND_LIB="$vgbasedir/.in_place" \
VALGRIND_LIB_INNER="$vgbasedir/.in_place" \
"$vgbasedir/coregrind/valgrind" "$@"
exec "$vgbasedir/coregrind/valgrind" "$@"