|
From: <sv...@va...> - 2005-09-22 15:38:50
|
Author: sewardj
Date: 2005-09-22 16:38:39 +0100 (Thu, 22 Sep 2005)
New Revision: 4722
Log:
Finish off first pass at command-line-arg handling. I'm less than
convinced I understand this stuff properly.
Modified:
branches/ASPACEM/coregrind/m_commandline.c
branches/ASPACEM/coregrind/m_main.c
branches/ASPACEM/coregrind/m_syswrap/syswrap-generic.c
branches/ASPACEM/coregrind/pub_core_main.h
Modified: branches/ASPACEM/coregrind/m_commandline.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- branches/ASPACEM/coregrind/m_commandline.c 2005-09-22 12:41:42 UTC (r=
ev 4721)
+++ branches/ASPACEM/coregrind/m_commandline.c 2005-09-22 15:38:39 UTC (r=
ev 4722)
@@ -80,6 +80,9 @@
=20
If args-for-v includes --command-line-only=3Dyes, then the extra
sources (env vars, files) are not consulted.
+
+ Note that args-for-c[0] is the first real arg for the client, not
+ its executable name.
*/
=20
=20
Modified: branches/ASPACEM/coregrind/m_main.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- branches/ASPACEM/coregrind/m_main.c 2005-09-22 12:41:42 UTC (rev 4721=
)
+++ branches/ASPACEM/coregrind/m_main.c 2005-09-22 15:38:39 UTC (rev 4722=
)
@@ -104,13 +104,6 @@
Startup stuff =20
------------------------------------------------------------------ */
=20
-/* The name of the stage1 (main) executable */
-static HChar* name_of_stage1 =3D NULL;
-
-/* our argc/argv */
-//static Int vg_argc;
-//static Char **vg_argv;
-
/* This should get some address inside the stack on which we gained
control (eg, it could be the SP at startup). It doesn't matter
exactly where in the stack it is. This value is passed to the
@@ -235,27 +228,33 @@
=20
If this is missing, then it is added.
=20
+ Also, remove any binding for VALGRIND_LAUNCHER=3D. The client should
+ not be able to see this.
+
If this needs to handle any more variables it should be hacked
into something table driven. The copy is VG_(malloc)'d space.
*/
static HChar** setup_client_env ( HChar** origenv, const HChar* toolname=
)
{
- static const HChar preload_core_so[] =3D "vg_preload_core.so";
- static const HChar ld_preload[] =3D "LD_PRELOAD=3D";
- static const Int ld_preload_len =3D sizeof(ld_preload)-1;
- Bool ld_preload_done =3D False;
- Int vgliblen =3D VG_(strlen)(VG_(libdir));
+ HChar* preload_core_so =3D "vg_preload_core.so";
+ HChar* ld_preload =3D "LD_PRELOAD=3D";
+ HChar* v_launcher =3D VALGRIND_LAUNCHER "=3D";
+ Int ld_preload_len =3D VG_(strlen)( ld_preload );
+ Int v_launcher_len =3D VG_(strlen)( v_launcher );
+ Bool ld_preload_done =3D False;
+ Int vglib_len =3D VG_(strlen)(VG_(libdir));
+
HChar** cpp;
HChar** ret;
HChar* preload_tool_path;;
- Int envc;
+ Int envc, i;
=20
/* Alloc space for the vgpreload_core.so path and vgpreload_<tool>.so
paths. We might not need the space for vgpreload_<tool>.so, but i=
t
doesn't hurt to over-allocate briefly. The 16s are just cautious
slop. */
- Int preload_core_path_len =3D vgliblen + sizeof(preload_core_so) + 16=
;
- Int preload_tool_path_len =3D vgliblen + VG_(strlen)(toolname) + 16=
;
+ Int preload_core_path_len =3D vglib_len + sizeof(preload_core_so) + 1=
6;
+ Int preload_tool_path_len =3D vglib_len + VG_(strlen)(toolname) + 1=
6;
Int preload_string_len =3D preload_core_path_len + preload_tool_pa=
th_len;
HChar* preload_string =3D VG_(malloc)(preload_string_len);
vg_assert(preload_string);
@@ -320,6 +319,18 @@
ret[envc++] =3D cp;
}
=20
+ /* ret[0 .. envc-1] is live now. */
+ /* Find and remove a binding for VALGRIND_LAUNCHER. */
+ for (i =3D 0; i < envc; i++)
+ if (0 =3D=3D VG_(memcmp(ret[i], v_launcher, v_launcher_len)))
+ break;
+
+ if (i < envc) {
+ for (; i < envc-1; i++)
+ ret[i] =3D ret[i+1];
+ envc--;
+ }
+
VG_(free)(preload_string);
ret[envc] =3D NULL;
=20
@@ -404,6 +415,7 @@
Addr client_SP; /* client stack base (initial SP) */
Addr clstack_start;
Int i;
+ Bool have_exename;
=20
vg_assert(VG_IS_PAGE_ALIGNED(clstack_end+1));
=20
@@ -413,7 +425,8 @@
/* =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D compu=
te sizes =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D */
=20
/* first of all, work out how big the client stack will be */
- stringsize =3D 0;
+ stringsize =3D 0;
+ have_exename =3D VG_(args_the_exename) !=3D NULL;
=20
/* paste on the extra args if the loader needs them (ie, the #!=20
interpreter and its argument) */
@@ -428,11 +441,14 @@
}
=20
/* now scan the args we're given... */
+ if (have_exename)
+ stringsize +=3D VG_(strlen)( VG_(args_the_exename) ) + 1;
+
for (i =3D 0; i < VG_(args_for_client).used; i++) {
argc++;
stringsize +=3D VG_(strlen)( VG_(args_for_client).strs[i] ) + 1;
}
- =20
+
/* ...and the environment */
envc =3D 0;
for (cpp =3D orig_envp; cpp && *cpp; cpp++) {
@@ -454,14 +470,15 @@
=20
/* OK, now we know how big the client stack is */
stacksize =3D
- sizeof(Word) + /* argc */
- sizeof(char **)*argc + /* argv */
- sizeof(char **) + /* terminal NULL */
- sizeof(char **)*envc + /* envp */
- sizeof(char **) + /* terminal NULL */
- auxsize + /* auxv */
- VG_ROUNDUP(stringsize, sizeof(Word)) +/* strings (aligned) */
- VKI_PAGE_SIZE; /* page for trampoline code */
+ sizeof(Word) + /* argc */
+ (have_exename ? sizeof(char **) : 0) + /* argc[0] =3D=3D exename =
*/
+ sizeof(char **)*argc + /* argv */
+ sizeof(char **) + /* terminal NULL */
+ sizeof(char **)*envc + /* envp */
+ sizeof(char **) + /* terminal NULL */
+ auxsize + /* auxv */
+ VG_ROUNDUP(stringsize, sizeof(Word)) + /* strings (aligned) */
+ VKI_PAGE_SIZE; /* page for trampoline code */
=20
if (0) VG_(printf)("stacksize =3D %d\n", stacksize);
=20
@@ -520,14 +537,14 @@
vg_assert(!res.isError);=20
}
=20
- /* =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D copy =
client stack =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
*/
+ /* =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D creat=
e client stack =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
*/
=20
ptr =3D (Addr*)client_SP;
=20
- /* --- argc --- */
- *ptr++ =3D argc; /* client argc */
+ /* --- client argc --- */
+ *ptr++ =3D argc + (have_exename ? 1 : 0);
=20
- /* --- argv --- */
+ /* --- client argv --- */
if (info->interp_name) {
*ptr++ =3D (Addr)copy_str(&strtab, info->interp_name);
VG_(free)(info->interp_name);
@@ -536,8 +553,12 @@
*ptr++ =3D (Addr)copy_str(&strtab, info->interp_args);
VG_(free)(info->interp_args);
}
- for (i =3D 0; i < VG_(args_for_client).used; ptr++, i++) {
- *ptr =3D (Addr)copy_str(&strtab, *cpp);
+
+ if (have_exename)
+ *ptr++ =3D (Addr)copy_str(&strtab, VG_(args_the_exename));
+
+ for (i =3D 0; i < VG_(args_for_client).used; i++) {
+ *ptr++ =3D (Addr)copy_str(&strtab, VG_(args_for_client).strs[i]);
}
*ptr++ =3D 0;
=20
@@ -1589,14 +1610,7 @@
}
}
=20
-// Build "/proc/self/fd/<execfd>".
-Char* VG_(build_child_exename)( void )
-{
- vg_assert(name_of_stage1);
- return VG_(arena_strdup)(VG_AR_CORE, name_of_stage1);
-}
=20
-
/*=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D*/
/*=3D=3D=3D File descriptor setup =
=3D=3D=3D*/
/*=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D*/
Modified: branches/ASPACEM/coregrind/m_syswrap/syswrap-generic.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- branches/ASPACEM/coregrind/m_syswrap/syswrap-generic.c 2005-09-22 12:=
41:42 UTC (rev 4721)
+++ branches/ASPACEM/coregrind/m_syswrap/syswrap-generic.c 2005-09-22 15:=
38:39 UTC (rev 4722)
@@ -2384,9 +2384,13 @@
// but it seems to work nonetheless...
PRE(sys_execve)
{
- Char* path; /* path to executable */
+ Char* path =3D NULL; /* path to executable */
Char** envp =3D NULL;
+ Char** argv =3D NULL;
+ Char** arg2copy;
+ Char* launcher_basename =3D NULL;
ThreadState* tst;
+ Int i, j, tot_args;
=20
PRINT("sys_execve ( %p(%s), %p, %p )", ARG1, ARG1, ARG2, ARG3);
PRE_REG_READ3(vki_off_t, "execve",
@@ -2397,17 +2401,15 @@
if (ARG3 !=3D 0)
pre_argv_envp( ARG3, tid, "execve(envp)", "execve(envp[i])" );
=20
- path =3D (Char *)ARG1;
-
vg_assert(VG_(is_valid_tid)(tid));
tst =3D VG_(get_ThreadState)(tid);
=20
/* Erk. If the exec fails, then the following will have made a
mess of things which makes it hard for us to continue. The
right thing to do is piece everything together again in
- POST(execve), but that's hard work. Instead, we make an effort
- to check that the execve will work before actually calling
- exec. */
+ POST(execve), but that's close to impossible. Instead, we make
+ an effort to check that the execve will work before actually
+ doing it. */
{
struct vki_stat st;
SysRes r =3D VG_(stat)((Char *)ARG1, &st);
@@ -2426,33 +2428,115 @@
}
}
=20
+ /* Check more .. that the name at least begins in client-accessible
+ storage. */
+ if (!VG_(am_is_valid_for_client)( ARG1, 1, VKI_PROT_READ )) {
+ SET_STATUS_Failure( VKI_EFAULT );
+ return;
+ }
+
+ /* After this point, we can't recover if the execve fails. */
+ VG_(debugLog)(1, "syswrap", "Exec of %s\n", (Char*)ARG1);
+
/* Resistance is futile. Nuke all other threads. POSIX mandates
this. (Really, nuke them all, since the new process will make
its own new thread.) */
VG_(nuke_all_threads_except)( tid, VgSrc_ExitSyscall );
VG_(reap_threads)(tid);
=20
+ // Set up the child's exe path.
+ //
+ if (VG_(clo_trace_children)) {
+
+ // We want to exec the launcher. Get its pre-remembered path.
+ path =3D VG_(name_of_launcher);
+ // VG_(name_of_launcher) should have been acquired by m_main at
+ // startup.
+ vg_assert(path);
+
+ launcher_basename =3D VG_(strrchr)(path, '/');
+ if (launcher_basename =3D=3D NULL || launcher_basename[1] =3D=3D 0=
) {
+ launcher_basename =3D path; // hmm, tres dubious
+ } else {
+ launcher_basename++;
+ }
+
+ } else {
+ path =3D (Char*)ARG1;
+ }
+
+ // Set up the child's environment.
+ //
// Remove the valgrind-specific stuff from the environment so the
// child doesn't get vg_preload_core.so, vg_preload_TOOL.so, etc. =20
// This is done unconditionally, since if we are tracing the child,
- // stage1/2 will set up the appropriate client environment.
+ // the child valgrind will set up the appropriate client environment.
// Nb: we make a copy of the environment before trying to mangle it
// as it might be in read-only memory (this was bug #101881).
- if (ARG3 !=3D 0) {
+ //
+ // Then, if tracing the child, set VALGRIND_LIB for it.
+ //
+ if (ARG3 =3D=3D 0) {
+ envp =3D NULL;
+ } else {
envp =3D VG_(env_clone)( (Char**)ARG3 );
+ if (envp =3D=3D NULL) goto hosed;
VG_(env_remove_valgrind_env_stuff)( envp );
}
=20
if (VG_(clo_trace_children)) {
// Set VALGRIND_LIB in ARG3 (the environment)
- VG_(env_setenv)( (Char***)&ARG3, VALGRIND_LIB, VG_(libdir));
+ VG_(env_setenv)( &envp, VALGRIND_LIB, VG_(libdir));
+ }
=20
- // Create executable name: "/proc/self/fd/<vgexecfd>", update ARG1
- path =3D VG_(build_child_exename)();
+ // Set up the child's args. If not tracing it, they are
+ // simply ARG2. Otherwise, they are
+ //
+ // [launcher_basename] ++ VG_(args_for_valgrind) ++ [ARG1] ++ ARG2[1.=
.]
+ //
+ // except that the first VG_(args_for_valgrind_noexecpass) args
+ // are omitted.
+ //
+ if (!VG_(clo_trace_children)) {
+ argv =3D (Char**)ARG2;
+ } else {
+ vg_assert( VG_(args_for_valgrind_noexecpass) >=3D 0 );
+ vg_assert( VG_(args_for_valgrind_noexecpass)=20
+ <=3D VG_(args_for_valgrind).used );
+ /* how many args in total will there be? */
+ // launcher basename
+ tot_args =3D 1;
+ // V's args
+ tot_args +=3D VG_(args_for_valgrind).used;
+ tot_args -=3D VG_(args_for_valgrind_noexecpass);
+ // name of client exe
+ tot_args++;
+ // args for client exe, skipping [0]
+ arg2copy =3D (Char**)ARG2;
+ if (arg2copy && arg2copy[0]) {
+ for (i =3D 1; arg2copy[i]; i++)
+ tot_args++;
+ }
+ // allocate
+ argv =3D VG_(malloc)( (tot_args+1) * sizeof(HChar*) );
+ if (argv =3D=3D 0) goto hosed;
+ // copy
+ j =3D 0;
+ argv[j++] =3D launcher_basename;
+ for (i =3D 0; i < VG_(args_for_valgrind).used; i++) {
+ if (i < VG_(args_for_valgrind_noexecpass))
+ continue;
+ argv[j++] =3D VG_(args_for_valgrind).strs[i];
+ }
+ argv[j++] =3D (Char*)ARG1;
+ if (arg2copy && arg2copy[0])
+ for (i =3D 1; arg2copy[i]; i++)
+ argv[j++] =3D arg2copy[i];
+ argv[j++] =3D NULL;
+ // check
+ vg_assert(j =3D=3D tot_args+1);
}
=20
- VG_(debugLog)(1, "syswrap", "Exec of %s\n", (HChar*)ARG1);
-
/* restore the DATA rlimit for the child */
VG_(setrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
=20
@@ -2477,9 +2561,8 @@
vki_sigset_t allsigs;
vki_siginfo_t info;
static const struct vki_timespec zero =3D { 0, 0 };
- Int i;
=20
- for(i =3D 1; i < VG_(max_signal); i++) {
+ for (i =3D 1; i < VG_(max_signal); i++) {
struct vki_sigaction sa;
VG_(do_sys_sigaction)(i, NULL, &sa);
if (sa.ksa_handler =3D=3D VKI_SIG_IGN)
@@ -2499,19 +2582,21 @@
=20
if (0) {
Char **cpp;
- VG_(printf)("exec: %s\n", (Char *)path);
- for (cpp =3D (Char **)ARG2; cpp && *cpp; cpp++)
+ VG_(printf)("exec: %s\n", path);
+ for (cpp =3D argv; cpp && *cpp; cpp++)
VG_(printf)("argv: %s\n", *cpp);
- for (cpp =3D (Char **)ARG3; cpp && *cpp; cpp++)
- VG_(printf)("env: %s\n", *cpp);
+ if (0)
+ for (cpp =3D envp; cpp && *cpp; cpp++)
+ VG_(printf)("env: %s\n", *cpp);
}
=20
SET_STATUS_from_SysRes(=20
- VG_(do_syscall3)(__NR_execve, (UWord)path, ARG2, ARG3)=20
+ VG_(do_syscall3)(__NR_execve, (UWord)path, (UWord)argv, (UWord)env=
p)=20
);
=20
- /* If we got here, then the execve failed. We've already made too
- much of a mess of ourselves to continue, so we have to abort. */
+ /* If we got here, then the execve failed. We've already made way
+ too much of a mess to continue, so we have to abort. */
+ hosed:
VG_(message)(Vg_UserMsg, "execve(%p(%s), %p, %p) failed, errno %d",
ARG1, ARG1, ARG2, ARG3, RES_unchecked);
VG_(message)(Vg_UserMsg, "EXEC FAILED: I can't recover from "
Modified: branches/ASPACEM/coregrind/pub_core_main.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- branches/ASPACEM/coregrind/pub_core_main.h 2005-09-22 12:41:42 UTC (r=
ev 4721)
+++ branches/ASPACEM/coregrind/pub_core_main.h 2005-09-22 15:38:39 UTC (r=
ev 4722)
@@ -38,9 +38,6 @@
// things.
//--------------------------------------------------------------------
=20
-// Help set up the child used when doing execve() with --trace-children=3D=
yes
-Char* VG_(build_child_exename) ( void );
-
// Do everything which needs doing before the process finally ends,
// like printing reports, etc
extern void VG_(shutdown_actions_NORETURN) (
|