o = VG_(open) (ptrace_scope_setting_file, VKI_O_RDONLY, 0);
if (sr_isError(o)) {
- sr_perror(o, "error VG_(open) %s\n", ptrace_scope_setting_file);
+ if (VG_(debugLog_getLevel)() >= 1) {
+ sr_perror(o, "error VG_(open) %s\n", ptrace_scope_setting_file);
+ }
/* can't read setting. Assuming ptrace can be called by vgdb. */
return;
}
"blocked in a system call *after* an initial successful attach\n",
ptrace_scope_setting_file);
} else if (ptrace_scope == 'X') {
- fprintf(stderr, "Could not determine ptrace scope from %s\n",
- ptrace_scope_setting_file);
+ DEBUG (1,
+ "PR_SET_PTRACER defined"
+ " but could not determine ptrace scope from %s\n",
+ ptrace_scope_setting_file);
}
if (fd >= 0)
close (fd);
" Only OPTION(s) can be given.\n"
"\n"
" OPTIONS are [--pid=<number>] [--vgdb-prefix=<prefix>]\n"
-" [--max-invoke-ms=<number>] [--wait=<number>] [-d] -D]\n"
+" [--max-invoke-ms=<number>] [--wait=<number>] [-d] [-D] [-l]\n"
" --pid arg must be given if multiple Valgrind gdbservers are found.\n"
" --vgdb-prefix arg must be given to both Valgrind and vgdb utility\n"
" if you want to change the default prefix for the FIFOs communication\n"
" is blocked in a system call).\n"
" -d arg tells to show debug info. Multiple -d args for more debug info\n"
" -D arg tells to show shared mem status and then exit.\n"
+" -l arg tells to show the list of running Valgrind gdbserver and then exit.\n"
+"\n"
+" -h --help shows this message\n"
+" To get help from the Valgrind gdbserver, use vgdb help\n"
"\n"
);
ptrace_restrictions();
}
-/* If arg_pid == -1, waits maximum check_trials seconds to discover
+/* If show_list, shows the list of Valgrind processes with gdbserver activated.
+ and then exits.
+
+ else if arg_pid == -1, waits maximum check_trials seconds to discover
a valgrind pid appearing.
+
Otherwise verify arg_pid is valid and corresponds to a Valgrind process
with gdbserver activated.
or exits in case of error (e.g. no pid found corresponding to arg_pid */
static
-int search_arg_pid(int arg_pid, int check_trials)
+int search_arg_pid(int arg_pid, int check_trials, Bool show_list)
{
int i;
int pid = -1;
/* try to find FIFOs with valid pid.
On exit of the loop, pid is set to:
+ the last pid found if show_list (or -1 if no process was listed)
-1 if no FIFOs matching a running process is found
-2 if multiple FIFOs of running processes are found
otherwise it is set to the (only) pid found that can be debugged
if (*wrongpid == '\0' && newpid > 0
&& kill (newpid, 0) == 0) {
nr_valid_pid++;
- if (arg_pid != -1) {
+ if (show_list) {
+ report_pid (newpid);
+ pid = newpid;
+ } else if (arg_pid != -1) {
if (arg_pid == newpid) {
pid = newpid;
}
free (vgdb_dir_name);
free (vgdb_format);
}
-
- if (pid == -1) {
+
+ if (show_list) {
+ exit (1);
+ } else if (pid == -1) {
if (arg_pid == -1)
fprintf (stderr, "vgdb error: no FIFO found and no pid given\n");
else
static
void parse_options(int argc, char** argv,
Bool *p_show_shared_mem,
+ Bool *p_show_list,
int *p_arg_pid,
int *p_check_trials,
int *p_last_command,
char *commands[])
{
Bool show_shared_mem = False;
+ Bool show_list = False;
int arg_pid = -1;
int check_trials = 1;
int last_command = -1;
debuglevel++;
} else if (is_opt(argv[i], "-D")) {
show_shared_mem = True;
+ } else if (is_opt(argv[i], "-l")) {
+ show_list = True;
} else if (is_opt(argv[i], "--pid=")) {
int newpid;
if (!numeric_val(argv[i], &newpid)) {
}
}
+
+ if (isatty(0)
+ && !show_shared_mem
+ && !show_list
+ && last_command == -1) {
+ arg_errors++;
+ fprintf (stderr,
+ "Using vgdb standalone implies to give -D or -l or a COMMAND\n");
+ }
+
+ if (show_shared_mem && show_list) {
+ arg_errors++;
+ fprintf (stderr,
+ "Can't use both -D and -l options\n");
+ }
+
+ if (show_list && arg_pid != -1) {
+ arg_errors++;
+ fprintf (stderr,
+ "Can't use both --pid and -l options\n");
+ }
+
if (arg_errors > 0) {
fprintf (stderr, "args error. Try `vgdb --help` for more information\n");
exit(1);
}
*p_show_shared_mem = show_shared_mem;
+ *p_show_list = show_list;
*p_arg_pid = arg_pid;
*p_check_trials = check_trials;
*p_last_command = last_command;
int pid;
Bool show_shared_mem;
+ Bool show_list;
int arg_pid;
int check_trials;
int last_command;
parse_options(argc, argv,
&show_shared_mem,
+ &show_list,
&arg_pid,
&check_trials,
&last_command,
if (max_invoke_ms > 0 || last_command == -1)
install_handlers();
- pid = search_arg_pid (arg_pid, check_trials);
+ pid = search_arg_pid (arg_pid, check_trials, show_list);
prepare_fifos_and_shared_mem(pid);
<para> Stack unwinding on PPC32/PPC64. </para>
<para> On PPC32/PPC64, stack unwinding for leaf functions
(i.e. functions not calling other functions) does work properly
- only with <option>--vex-iropt-precise-memory-exns=yes</option>
+ only with <option>--vex-iropt-precise-memory-exns=yes</option>.
+ You must also pass this option to have a precise stack when
+ a signal is trapped by gdb.
</para>
</listitem>
shared memory used by the Valgrind gdbserver. vgdb will exit after
having shown the Valgrind gdbserver shared memory state.</para>
</listitem>
+
+ <listitem>
+ <para><option>-l</option> instructs vgdb to report the list of
+ the Valgrind gdbserver processes running and then exit.</para>
+ </listitem>
</itemizedlist>
</sect1>
read/write from stdin/stdout.
The tests have been run on various platforms using gdb 7.2
-and on some platforms gdb 7.0.
+and on some platforms gdb 7.0 and 7.1.
Some gdb tests implies a gdb >= 7.2. (these are automatically disabled
if testing with a lower version).
+Test behaviour with gdb < 7.0 is unknown: some might fail,
+some might block or loop for a very long time.
Some tests implies to have a vgdb "ptrace invoker" capable.
In case of failing tests
------------------------
-gdbserver tests are often failing due to (irrelevant) differences
-depending on the gdb version and/or the OS version.
+When executed with a new gdb version and/or depending on the OS version,
+gdbserver tests might often fail due to (irrelevant) differences.
Such irrelevant differences have to be filtered by gdbserver_tests/filter_gdb.
-To report such problems, the best is to re-run the gdbserver tests
-the following way:
+You are welcome to fix such bugs by enhancing filter_gdb.
+
+Alternatively, to report such problems, the best is to re-run
+the gdbserver tests the following way:
perl tests/vg_regtest --keep-unfiltered gdbserver_tests
Then file a bug in bugzilla, giving the following information:
uname -a
cat /etc/issue
valgrind --version (and/or svn version)
- and attach a tar file containing all the *.out files in gdbserver_tests
- directory
+ and attach a tar file containing all the *.out and *.diff
+ files in gdbserver_tests directory
+
+If a gdbserver test fails for other reasons, you can run the test
+manually in two windows:
+ In one window, the valgrind
+ In another window, you launch gdb yourself, and you copy paste
+ the command from xxxx.stdinB.gdb. This might help to see what is
+ wrong.
+
+Another good trick is also to execute the same kind of actions
+using a gdb connected to the gdbserver part of gdb.
+You can examine what is happening by enabling the trace
+of the packets being sent using the gdb command:
+ set debug remote 1
+Note however that the packets might be different
+(e.g. the Valgrind gdbserver understands the 'P' packet,
+which might not be understood by the gdbserver of gdb).
Naming conventions:
-------------------
# which registers can't be modified
# special transform for arm/ppc watchpoints which have an additional address
# at the beginning
-# special transform for backtrace of arm division by zero which gives
+# special transform for backtrace of arm or ppc division by zero which gives
# a location in the nptl lib rather than our sources (same as
# standard gdb gdbserver) gdb 7.0
# same special transform but for gdb 7.2
# a.o. produced by gdb 7.2 on arm (same with standard gdbserver)
# delete empty lines (the last line (only made of prompts) sometimes
# finishes with a new line, sometimes not ???).
-sed -e '/Remote debugging using/,/vgdb launched process attached/d' \
+sed -e '/Remote debugging using/,/vgdb launched process attached/d' \
-e 's/^\e\[?1034hReading symbols/Reading symbols/' \
- -e '/Missing separate debuginfos, use: debuginfo-install/d' \
+ -e '/^Missing separate debuginfo/d' \
+ -e '/^Try: zypper install -C/d' \
-e 's/\(relaying data between gdb and process \)[0-9][0-9]*/\1..../' \
-e 's/pid [0-9][0-9]*/pid ..../g' \
-e 's/Thread [0-9][0-9]*/Thread ..../g' \
-e 's/in _dl_sysinfo_int80 () from \/lib\/ld-linux.so.*/in syscall .../' \
-e 's/in _dl_sysinfo_int80 ()/in syscall .../' \
-e '/^ from \/lib\/ld-linux.so.*$/d' \
- -e 's/\(0x........\) in ?? () from \/lib\/ld-linux\.so\../\1 in syscall .../' \
- -e 's/\(0x........\) in ?? () from \/lib64\/tls\/libc\.so\../\1 in syscall .../' \
+ -e 's/\(0x........\) in ?? () from \/lib.*$/\1 in syscall .../' \
-e 's/\(0x........\) in ?? ()$/\1 in syscall .../' \
-e 's/in \(.__\)\{0,1\}select () from \/.*$/in syscall .../' \
-e '/^ from \/lib\/libc.so.*$/d' \
-e 's/\(ERROR changing register \).*$/\1 xxx regno y/' \
-e 's/0x........ in \(main (argc=1, argv=0x........) at watchpoints.c:[24][3689]\)/\1/' \
-e 's/0x........ in \(main () at clean_after_fork.c:32\)/\1/' \
- -e 's/0x........ in \*__GI_raise (sig=8)/0x........ in test4 () at faultstatus.c:120/' \
- -e 's/ at ..\/nptl\/sysdeps\/unix\/sysv\/linux\/raise.c:[0-9]*/120 volatile int v = 44\/zero();/' \
+ -e 's/^0x........ in \*__GI_raise (sig=8).*/0x........ in test4 () at faultstatus.c:120\n120 volatile int v = 44\/zero();/' \
+ -e '/ at ..\/nptl\/sysdeps\/unix\/sysv\/linux\/raise.c:[0-9]*/d' \
-e '/ in ..\/nptl\/sysdeps\/unix\/sysv\/linux\/raise.c/d' \
- -e 's/0x........ in \.\{0,1\}raise () from \/lib[0-9]\{0,2\}\/libc\.so\../0x........ in test4 () at faultstatus.c:120\n120 volatile int v = 44\/zero();'/ \
+ -e 's/^0x........ in \.\{0,1\}raise () from \/lib[0-9]\{0,2\}\/libc\.so\../0x........ in test4 () at faultstatus.c:120\n120 volatile int v = 44\/zero();'/ \
-e '/Cannot access memory at address 0x......../d' \
-e '/^$/d' |
#! /bin/sh
-# used to filter memcheck output shown by vgdb.
+# used to filter memcheck output shown by gdb/vgdb.
dir=`dirname $0`
$dir/filter_vgdb |
+
+# filter some normal error messages provided by some gdb
+#
+# gdb 7.2 sometimes tries to access address 0x0 (same as with standard gdbserver)
+#
+# filter a debian 6.0/ppc32 line
+#
+# filter some missing info msg from s390
+#
# Bypass a s390x kernel bug which makes faultstatus test3 fail. In our case, we are
# not interested in checking the si_code, but rather the signal passing
# in mcsig(no)pass
-sed -e 's/Test 3: FAIL: expected si_code==2, not 128/Test 3: PASS/'
+sed -e '/Cannot access memory at address 0x......../d' \
+ -e '/^[1-9][0-9]* \.\.\/sysdeps\/powerpc\/powerpc32\/dl-start\.S: No such file or directory\./d' \
+ -e '/^Missing separate debuginfo/d' \
+ -e '/^Try: zypper install -C/d' \
+ -e 's/Test 3: FAIL: expected si_code==2, not 128/Test 3: PASS/'
prog: t
vgopts: --tool=memcheck --vgdb=yes --vgdb-error=0 --vgdb-prefix=./vgdb-prefix-mcbreak
stdout_filter: filter_gdb
-#stdout_filter: /bin/cat
stderr_filter: filter_make_empty
progB: gdb
argsB: --quiet -l 60 --nx ./t
stdinB: mcbreak.stdinB.gdb
stdoutB_filter: filter_gdb
-#stdoutB_filter: /bin/cat
stderrB_filter: filter_memcheck_monitor
# too much dependencies to the scheduler fairness.
args: 1 0 2000000000 ------B-
vgopts: --tool=memcheck --vgdb=yes --vgdb-error=0 --vgdb-prefix=./vgdb-prefix-mcinfcallRU
-# filter_gdb to replace pid and Thread numbers.
-# Well, the test will verify we have 4 calls (for each thread)
-# but no way to check that this is effectively in the 4 different threads.
+# filter_gdb to replace pid and Thread numbers in the output of the program:
stderr_filter: filter_gdb
# Disable on Darwin: inferior call rejected as it cannot find malloc.
prereq: test -e gdb && ../tests/os_test linux
vgopts: --tool=memcheck --vgdb=yes --vgdb-error=0 --vgdb-prefix=./vgdb-prefix-mcinfcallWSRU
# Disable on Darwin: inferior call rejected as it cannot find malloc.
prereq: test -e gdb && ../tests/os_test linux
-# filter_gdb to replace pid and Thread numbers.
+# filter_gdb to replace pid and Thread numbers in the output of the program:
stderr_filter: filter_gdb
progB: gdb
argsB: --quiet -l 60 --nx 1>&2 ./sleepers
# are eventually passed.
prereq: test -e gdb
prog: ../none/tests/faultstatus
-vgopts: --tool=memcheck --vgdb=full --vgdb-error=0 --vgdb-prefix=./vgdb-prefix-mcsignopass
+vgopts: --tool=memcheck --vgdb=full --vex-iropt-precise-memory-exns=yes --vgdb-error=0 --vgdb-prefix=./vgdb-prefix-mcsignopass
stderr_filter: filter_memcheck_monitor
progB: gdb
argsB: --quiet -l 60 --nx ../none/tests/faultstatus
# test the signal handling, when signals are passed to the Valgrind guest.
prereq: test -e gdb
prog: ../none/tests/faultstatus
-vgopts: --tool=memcheck --vgdb=full --vgdb-error=0 --vgdb-prefix=./vgdb-prefix-mcsigpass
+vgopts: --tool=memcheck --vgdb=full --vex-iropt-precise-memory-exns=yes --vgdb-error=0 --vgdb-prefix=./vgdb-prefix-mcsigpass
stderr_filter: filter_memcheck_monitor
progB: gdb
argsB: --quiet -l 60 --nx ../none/tests/faultstatus
vg.set vgdb-error <errornr> : debug me at error >= <errornr>
massif monitor commands:
- ms.snapshot [<filename>] [detailed]
- takes a snapshot and saves it in <filename>
+ ms.snapshot [<filename>]
+ ms.detailed_snapshot [<filename>]
+ takes a snapshot (or a detailed snapshot)
+ and saves it in <filename>
default <filename> is massif.vgdb.out
- if present, detailed argument indicates to take a detailed snapshot
monitor command request to kill this process
Remote connection closed
#
# test non detailed and detailed snapshot
monitor ms.snapshot
-monitor ms.snapshot detailed
+monitor ms.detailed_snapshot
#
#
monitor vg.kill
progB: gdb
argsB: --quiet -l 60 --nx ./sleepers
stdinB: nlcontrolc.stdinB.gdb
-#stdoutB_filter: /bin/cat
stdoutB_filter: filter_gdb
-#stderrB_filter: /bin/cat
stderrB_filter: filter_make_empty
<itemizedlist>
<listitem>
- <para><varname>ms.snapshot [<filename>] [detailed]</varname> requests to take
- a snapshot and save it in the given <filename> (default massif.vgdb.out).
- If present, the 'detailed' argument indicates to take a detailed snapshot.
+ <para><varname>ms.snapshot [<filename>]</varname> requests
+ to take a snapshot and save it in the given <filename>
+ (default massif.vgdb.out).
+ </para>
+ </listitem>
+ <listitem>
+ <para><varname>ms.detailed_snapshot [<filename>]</varname>
+ requests to take a detailed snapshot and save it in the given
+ <filename> (default massif.vgdb.out).
</para>
</listitem>
</itemizedlist>
{
VG_(gdb_printf) ("\n");
VG_(gdb_printf) ("massif monitor commands:\n");
- VG_(gdb_printf) (" ms.snapshot [<filename>] [detailed]\n");
- VG_(gdb_printf) (" takes a snapshot and saves it in <filename>\n");
+ VG_(gdb_printf) (" ms.snapshot [<filename>]\n");
+ VG_(gdb_printf) (" ms.detailed_snapshot [<filename>]\n");
+ VG_(gdb_printf) (" takes a snapshot (or a detailed snapshot)\n");
+ VG_(gdb_printf) (" and saves it in <filename>\n");
VG_(gdb_printf) (" default <filename> is massif.vgdb.out\n");
- VG_(gdb_printf) (" if present, detailed argument indicates to take a detailed snapshot\n");
VG_(gdb_printf) ("\n");
}
VG_(free)(massif_out_file);
}
+static handle_snapshot_monitor_command (Char *filename, Bool detailed)
+{
+ Snapshot snapshot;
+
+ clear_snapshot(&snapshot, /* do_sanity_check */ False);
+ take_snapshot(&snapshot, Normal, get_time(), detailed);
+ write_snapshots_to_file ((filename == NULL) ? (Char*) "massif.vgdb.out" : filename,
+ &snapshot,
+ 1);
+ delete_snapshot(&snapshot);
+}
+
static Bool handle_gdb_monitor_command (ThreadId tid, Char *req)
{
Char* wcmd;
VG_(strcpy) (s, req);
wcmd = VG_(strtok_r) (s, " ", &ssaveptr);
- switch (VG_(keyword_id) ("help ms.snapshot",
+ switch (VG_(keyword_id) ("help ms.snapshot ms.detailed_snapshot",
wcmd, kwd_report_duplicated_matches)) {
case -2: /* multiple matches */
return True;
print_monitor_help();
return True;
case 1: { /* ms.snapshot */
- Char* kw;
- Char* filename = NULL;
- Bool detailed = False;
- Snapshot snapshot;
-
- for (kw = VG_(strtok_r) (NULL, " ", &ssaveptr);
- kw != NULL;
- kw = VG_(strtok_r) (NULL, " ", &ssaveptr)) {
- if (filename == NULL)
- filename = kw;
- else if (0 == VG_(strncmp)(kw, "detailed", VG_(strlen) (kw)))
- detailed = True;
- else {
- VG_(gdb_printf) ("invalid 2nd arg\n");
- return True;
- }
- }
- clear_snapshot(&snapshot, /* do_sanity_check */ False);
- take_snapshot(&snapshot, Normal, get_time(), detailed);
- write_snapshots_to_file ((filename == NULL) ? (Char*) "massif.vgdb.out" : filename,
- &snapshot,
- 1);
- delete_snapshot(&snapshot);
+ Char* filename;
+ filename = VG_(strtok_r) (NULL, " ", &ssaveptr);
+ handle_snapshot_monitor_command (filename, False /* detailed */);
+ return True;
+ }
+ case 2: { /* ms.detailed_snapshot */
+ Char* filename;
+ filename = VG_(strtok_r) (NULL, " ", &ssaveptr);
+ handle_snapshot_monitor_command (filename, True /* detailed */);
return True;
}
default: