From: Julian Seward Date: Mon, 19 Mar 2007 18:38:55 +0000 (+0000) Subject: Make ptrace-based launchers able to handle --help, --version etc. X-Git-Tag: svn/VALGRIND_3_3_0~313 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=14b9b8b8d2e043b8c689c1ff053989c86b6686bf;p=thirdparty%2Fvalgrind.git 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 --- diff --git a/coregrind/Makefile.am b/coregrind/Makefile.am index 578e77db54..d725ad40d5 100644 --- a/coregrind/Makefile.am +++ b/coregrind/Makefile.am @@ -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) # #---------------------------------------------------------- diff --git a/coregrind/launcher-aix5.c b/coregrind/launcher-aix5.c index eaa2dc7913..775e51d56c 100644 --- a/coregrind/launcher-aix5.c +++ b/coregrind/launcher-aix5.c @@ -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//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"); diff --git a/coregrind/m_initimg/initimg-aix5.c b/coregrind/m_initimg/initimg-aix5.c index 5033be79e6..cf02dacc27 100644 --- a/coregrind/m_initimg/initimg-aix5.c +++ b/coregrind/m_initimg/initimg-aix5.c @@ -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*/ diff --git a/coregrind/m_main.c b/coregrind/m_main.c index 84fb4e39fc..0c8bebc7a0 100644 --- a/coregrind/m_main.c +++ b/coregrind/m_main.c @@ -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, diff --git a/coregrind/no_op_client_for_valgrind.c b/coregrind/no_op_client_for_valgrind.c new file mode 100644 index 0000000000..5956607b0b --- /dev/null +++ b/coregrind/no_op_client_for_valgrind.c @@ -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 +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; +}