Make ptrace-based launchers able to handle --help, --version etc.

Problem is that --help etc are handled by the tool exe.  But a
ptrace-based launch scheme can't run "no program" if the user just
types "valgrind --help" because the launcher depends on starting the
client first and only then attaching valgrind to it using ptrace.  So
instead provide a dummy do-nothing program to run when no program is
specified.  m_main notices this and acts as if there really had been
no program specified.

This has no effect at all on Linux/ELF program launching.



git-svn-id: svn://svn.valgrind.org/valgrind/trunk@6653
This commit is contained in:
Julian Seward 2007-03-19 18:38:55 +00:00
parent a64b0bfb0c
commit 14b9b8b8d2
5 changed files with 77 additions and 4 deletions

View File

@ -42,7 +42,7 @@ endif
# Build the launcher (valgrind) for the primary target only.
#
bin_PROGRAMS = \
valgrind
valgrind no_op_client_for_valgrind
if VGO_AIX5
valgrind_SOURCES = \
@ -59,6 +59,10 @@ valgrind_CPPFLAGS = $(AM_CPPFLAGS_PRI)
valgrind_CFLAGS = $(AM_CFLAGS_PRI)
valgrind_CCASFLAGS = $(AM_CCASFLAGS_PRI)
valgrind_LDFLAGS = $(AM_CFLAGS_PRI)
no_op_client_for_valgrind_SOURCES = no_op_client_for_valgrind.c
no_op_client_for_valgrind_CPPFLAGS = $(AM_CPPFLAGS_PRI)
no_op_client_for_valgrind_CFLAGS = $(AM_CFLAGS_PRI)
#
#----------------------------------------------------------

View File

@ -1329,7 +1329,7 @@ int main ( int argc, char** argv, char** envp )
Child child;
Int i, loglevel;
const char *toolname = NULL;
const char *clientname = NULL;
char *clientname = NULL;
/* First, look in our own /proc/<pid>/sysent file to find
the syscall numbers for kwrite and _getpid. These are needed
@ -1421,6 +1421,44 @@ int main ( int argc, char** argv, char** envp )
assert(PAGE_SIZE == 4096); /* stay sane */
const char* valgrind_lib = VG_LIBDIR;
/* If there is no program to run, which will be the case if the
user just does "valgrind --help", etc, run a dummy do-nothing
program so at least the tool can get started and handle the
--help/--version etc. It spots the fact that this is a dummy
program and acts like it was started with no program, hence
behaving the same as the Linux ports would have. */
if (clientname == NULL) {
Int j;
char** new_argv;
const char* noop_exe_name = "no_op_client_for_valgrind";
const char* up_n_bindir = "/../../bin";
clientname = malloc(strlen(valgrind_lib) + strlen(up_n_bindir)
+ 2 + strlen(noop_exe_name));
if (clientname == NULL) {
fprintf(stderr,"%s: malloc of clientname failed\n", argv[0]);
return 1;
}
sprintf(clientname, "%s%s/%s", valgrind_lib, up_n_bindir, noop_exe_name);
/* now we have to add it to the end of argv, which means making
that one word longer. How tedious. */
for (j = 0; argv[j]; j++)
;
j += 2;
new_argv = calloc(j, sizeof(char*));
if (new_argv == NULL) {
fprintf(stderr,"%s: malloc of new_argv failed\n", argv[0]);
return 1;
}
for (i = 0; i < j-2; i++)
new_argv[i] = argv[i];
new_argv[j-2] = clientname;
assert(new_argv[j-1] == NULL);
argv = new_argv;
argc++;
}
if (argc < 2 || toolname == NULL || clientname == NULL)
barf(1, argv[0], "usage: valgrind [args-for-valgrind] prog args");
@ -1428,7 +1466,7 @@ int main ( int argc, char** argv, char** envp )
executable. */
VG_(debugLog)(1, "launcher", "searching for client in $PATH\n");
if (strchr(clientname, '/') == NULL)
clientname = find_client(clientname);
clientname = (char*)find_client(clientname);
VG_(debugLog)(1, "launcher", "found %s\n", clientname);
Int client_exekind = examine_client ( clientname );
@ -1450,7 +1488,6 @@ int main ( int argc, char** argv, char** envp )
VG_(debugLog)(1, "launcher", "client is an XCOFF%d executable\n",
client_exekind);
const char* valgrind_lib = VG_LIBDIR;
const char* platform = child.is64 ? "ppc64-aix5" : "ppc32-aix5";
VG_(debugLog)(1, "launcher", "looking for the tool file\n");

View File

@ -96,6 +96,10 @@ IIFinaliseImageInfo VG_(ii_create_image)( IICreateImageInfo iicii )
IIFinaliseImageInfo iifii;
VG_(memset)( &iifii, 0, sizeof(iifii) );
/* this can happen, if m_main decides to NULL it out */
if (VG_(args_the_exename) == NULL)
VG_(err_missing_prog)();
vg_assert( iicii.toolname );
pltool_len = VG_(strlen)( VG_(libdir) )
+ 1 /*slash*/

View File

@ -1399,6 +1399,18 @@ Int valgrind_main ( Int argc, HChar **argv, HChar **envp )
);
}
# if defined(VGO_aix5)
/* Tolerate ptraced-based launchers. They can't run 'no program'
if the user types "valgrind --help", so they run a do-nothing
program $prefix/bin/no_op_client_for_valgrind, and we catch that
here and turn it the exe name back into NULL. Then --help,
--version etc work as they should. */
if (VG_(args_the_exename)
&& VG_(strstr)( VG_(args_the_exename), "/no_op_client_for_valgrind" )) {
VG_(args_the_exename) = NULL;
}
# endif
//--------------------------------------------------------------
// Extract tool name and whether help has been requested.
// Note we can't print the help message yet, even if requested,

View File

@ -0,0 +1,16 @@
/* This program doesn't do anything. So why is it here? It's a
helper for ptraced-based launchers (eg aix5). They can't run 'no
program' if the user types "valgrind --help", so they run this
do-nothing program. m_main notices that and turns the exe name
back into NULL. Then --help, --version etc work as they should. */
#include <stdio.h>
int main ( void )
{
fprintf(stderr,
"This program (part of Valgrind) does nothing except print\n"
"this text. You should not see this text. If you do, some\n"
"part of valgrind's launch mechanism is not working correctly.\n");
return 0;
}