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 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/Makefile.am b/coregrind/Makefile.am
index 578e77d..d725ad4 100644
--- a/coregrind/Makefile.am
+++ b/coregrind/Makefile.am
@@ -42,7 +42,7 @@
# 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_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 eaa2dc7..775e51d 100644
--- a/coregrind/launcher-aix5.c
+++ b/coregrind/launcher-aix5.c
@@ -1329,7 +1329,7 @@
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 @@
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 @@
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 @@
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 5033be7..cf02dac 100644
--- a/coregrind/m_initimg/initimg-aix5.c
+++ b/coregrind/m_initimg/initimg-aix5.c
@@ -96,6 +96,10 @@
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 84fb4e3..0c8bebc 100644
--- a/coregrind/m_main.c
+++ b/coregrind/m_main.c
@@ -1399,6 +1399,18 @@
);
}
+# 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 0000000..5956607
--- /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 <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;
+}