1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Process-related libc stuff. m_libcproc.c ---*/ 4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This file is part of Valgrind, a dynamic binary instrumentation 8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown framework. 9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 10663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Copyright (C) 2000-2012 Julian Seward 11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown jseward@acm.org 12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This program is free software; you can redistribute it and/or 14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown modify it under the terms of the GNU General Public License as 15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown published by the Free Software Foundation; either version 2 of the 16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown License, or (at your option) any later version. 17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This program is distributed in the hope that it will be useful, but 19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown WITHOUT ANY WARRANTY; without even the implied warranty of 20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown General Public License for more details. 22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown You should have received a copy of the GNU General Public License 24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown along with this program; if not, write to the Free Software 25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 02111-1307, USA. 27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The GNU General Public License is contained in the file COPYING. 29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_basics.h" 32663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#include "pub_core_machine.h" // For VG_(machine_get_VexArchInfo) 33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_vki.h" 34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_vkiscnums.h" 35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcbase.h" 36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcassert.h" 37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcprint.h" 38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcproc.h" 39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcsignal.h" 40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_seqmatch.h" 41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_mallocfree.h" 42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_syscall.h" 43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_xarray.h" 44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_clientstate.h" 45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_darwin) 47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --- !!! --- EXTERNAL HEADERS start --- !!! --- */ 48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <mach/mach.h> /* mach_thread_self */ 49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --- !!! --- EXTERNAL HEADERS end --- !!! --- */ 50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* IMPORTANT: on Darwin it is essential to use the _nocancel versions 53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown of syscalls rather than the vanilla version, if a _nocancel version 54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown is available. See docs/internals/Darwin-notes.txt for the reason 55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown why. */ 56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Command line and environment stuff 59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* As deduced from sp_at_startup, the client's argc, argv[] and 62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown envp[] as extracted from the client's stack at startup-time. */ 63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownChar** VG_(client_envp) = NULL; 64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Path to library directory */ 66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst Char *VG_(libdir) = VG_LIBDIR; 67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst Char *VG_(LD_PRELOAD_var_name) = 69b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#if defined(VGO_linux) 70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "LD_PRELOAD"; 71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#elif defined(VGO_darwin) 72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "DYLD_INSERT_LIBRARIES"; 73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else 74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error Unknown OS 75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* We do getenv without libc's help by snooping around in 78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(client_envp) as determined at startup time. */ 79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownChar *VG_(getenv)(Char *varname) 80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i, n; 82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert( VG_(client_envp) ); 83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n = VG_(strlen)(varname); 84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; VG_(client_envp)[i] != NULL; i++) { 85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char* s = VG_(client_envp)[i]; 86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(strncmp)(varname, s, n) == 0 && s[n] == '=') { 87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return & s[n+1]; 88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return NULL; 91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(env_unsetenv) ( Char **env, const Char *varname ) 94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 95b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Char **from, **to; 96b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(env); 97b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(varname); 98b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov to = NULL; 99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int len = VG_(strlen)(varname); 100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (from = to = env; from && *from; from++) { 102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!(VG_(strncmp)(varname, *from, len) == 0 && (*from)[len] == '=')) { 103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *to = *from; 104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown to++; 105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *to = *from; 108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* set the environment; returns the old env if a new one was allocated */ 111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownChar **VG_(env_setenv) ( Char ***envp, const Char* varname, const Char *val ) 112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char **env = (*envp); 114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char **cpp; 115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int len = VG_(strlen)(varname); 116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char *valstr = VG_(arena_malloc)(VG_AR_CORE, "libcproc.es.1", 117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown len + VG_(strlen)(val) + 2); 118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char **oldenv = NULL; 119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf)(valstr, "%s=%s", varname, val); 121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (cpp = env; cpp && *cpp; cpp++) { 123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(strncmp)(varname, *cpp, len) == 0 && (*cpp)[len] == '=') { 124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *cpp = valstr; 125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return oldenv; 126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (env == NULL) { 130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown env = VG_(arena_malloc)(VG_AR_CORE, "libcproc.es.2", sizeof(Char **) * 2); 131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown env[0] = valstr; 132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown env[1] = NULL; 133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *envp = env; 135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int envlen = (cpp-env) + 2; 138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char **newenv = VG_(arena_malloc)(VG_AR_CORE, "libcproc.es.3", 139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown envlen * sizeof(Char **)); 140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (cpp = newenv; *env; ) 142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *cpp++ = *env++; 143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *cpp++ = valstr; 144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *cpp++ = NULL; 145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown oldenv = *envp; 147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *envp = newenv; 149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return oldenv; 152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Walk through a colon-separated environment variable, and remove the 156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown entries which match remove_pattern. It slides everything down over 157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the removed entries, and pads the remaining space with '\0'. It 158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown modifies the entries in place (in the client address space), but it 159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown shouldn't matter too much, since we only do this just before an 160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown execve(). 161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This is also careful to mop up any excess ':'s, since empty strings 163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown delimited by ':' are considered to be '.' in a path. 164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void mash_colon_env(Char *varp, const Char *remove_pattern) 166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char *const start = varp; 168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char *entry_start = varp; 169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char *output = varp; 170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (varp == NULL) 172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while(*varp) { 175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (*varp == ':') { 176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char prev; 177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool match; 178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* This is a bit subtle: we want to match against the entry 180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown we just copied, because it may have overlapped with 181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown itself, junking the original. */ 182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown prev = *output; 184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *output = '\0'; 185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown match = VG_(string_match)(remove_pattern, entry_start); 187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *output = prev; 189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (match) { 191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown output = entry_start; 192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown varp++; /* skip ':' after removed entry */ 193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else 194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown entry_start = output+1; /* entry starts after ':' */ 195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (*varp) 198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *output++ = *varp++; 199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* make sure last entry is nul terminated */ 202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *output = '\0'; 203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* match against the last entry */ 205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(string_match)(remove_pattern, entry_start)) { 206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown output = entry_start; 207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (output > start) { 208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* remove trailing ':' */ 209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown output--; 210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(*output == ':'); 211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* pad out the left-overs with '\0' */ 215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while(output < varp) 216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *output++ = '\0'; 217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Removes all the Valgrind-added stuff from the passed environment. Used 221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// when starting child processes, so they don't see that added stuff. 222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(env_remove_valgrind_env_stuff)(Char** envp) 223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGO_darwin) 226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Environment cleanup is also handled during parent launch 228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // in vg_preloaded.c:vg_cleanup_env(). 229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif 231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i; 233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char* ld_preload_str = NULL; 234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char* ld_library_path_str = NULL; 235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char* dyld_insert_libraries_str = NULL; 236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char* buf; 237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Find LD_* variables 239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // DDD: should probably conditionally compiled some of this: 240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // - LD_LIBRARY_PATH is universal? 241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // - LD_PRELOAD is on Linux, not on Darwin, not sure about AIX 242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // - DYLD_INSERT_LIBRARIES and DYLD_SHARED_REGION are Darwin-only 243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; envp[i] != NULL; i++) { 244663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (VG_(strncmp)(envp[i], "LD_PRELOAD=", 11) == 0) { 245663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng envp[i] = VG_(arena_strdup)(VG_AR_CORE, "libcproc.erves.1", envp[i]); 246663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ld_preload_str = &envp[i][11]; 247663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 248663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (VG_(strncmp)(envp[i], "LD_LIBRARY_PATH=", 16) == 0) { 249663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng envp[i] = VG_(arena_strdup)(VG_AR_CORE, "libcproc.erves.2", envp[i]); 250663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ld_library_path_str = &envp[i][16]; 251663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 252663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (VG_(strncmp)(envp[i], "DYLD_INSERT_LIBRARIES=", 22) == 0) { 253663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng envp[i] = VG_(arena_strdup)(VG_AR_CORE, "libcproc.erves.3", envp[i]); 254663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng dyld_insert_libraries_str = &envp[i][22]; 255663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 258b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov buf = VG_(arena_malloc)(VG_AR_CORE, "libcproc.erves.4", 259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(strlen)(VG_(libdir)) + 20); 260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Remove Valgrind-specific entries from LD_*. 262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf)(buf, "%s*/vgpreload_*.so", VG_(libdir)); 263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mash_colon_env(ld_preload_str, buf); 264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mash_colon_env(dyld_insert_libraries_str, buf); 265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sprintf)(buf, "%s*", VG_(libdir)); 266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mash_colon_env(ld_library_path_str, buf); 267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Remove VALGRIND_LAUNCHER variable. 269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(env_unsetenv)(envp, VALGRIND_LAUNCHER); 270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Remove DYLD_SHARED_REGION variable. 272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(env_unsetenv)(envp, "DYLD_SHARED_REGION"); 273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // XXX if variable becomes empty, remove it completely? 275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(arena_free)(VG_AR_CORE, buf); 277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Various important syscall wrappers 281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(waitpid)(Int pid, Int *status, Int options) 284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGO_linux) 286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res = VG_(do_syscall4)(__NR_wait4, 287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pid, (UWord)status, options, 0); 288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? -1 : sr_Res(res); 289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGO_darwin) 290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res = VG_(do_syscall4)(__NR_wait4_nocancel, 291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pid, (UWord)status, options, 0); 292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? -1 : sr_Res(res); 293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error Unknown OS 295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* clone the environment */ 299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownChar **VG_(env_clone) ( Char **oldenv ) 300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char **oldenvp; 302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char **newenvp; 303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char **newenv; 304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int envlen; 305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 306b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov vg_assert(oldenv); 307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (oldenvp = oldenv; oldenvp && *oldenvp; oldenvp++); 308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown envlen = oldenvp - oldenv + 1; 310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown newenv = VG_(arena_malloc)(VG_AR_CORE, "libcproc.ec.1", 312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown envlen * sizeof(Char **)); 313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown oldenvp = oldenv; 315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown newenvp = newenv; 316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (oldenvp && *oldenvp) { 318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *newenvp++ = *oldenvp++; 319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *newenvp = *oldenvp; 322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return newenv; 324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(execv) ( Char* filename, Char** argv ) 327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char** envp; 329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* restore the DATA rlimit for the child */ 332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(setrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data)); 333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown envp = VG_(env_clone)(VG_(client_envp)); 335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(env_remove_valgrind_env_stuff)( envp ); 336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall3)(__NR_execve, 338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (UWord)filename, (UWord)argv, (UWord)envp); 339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(printf)("EXEC failed, errno = %lld\n", (Long)sr_Err(res)); 341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Return -1 if error, else 0. NOTE does not indicate return code of 344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown child! */ 345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(system) ( Char* cmd ) 346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int pid; 348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (cmd == NULL) 349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 1; 350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pid = VG_(fork)(); 351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (pid < 0) 352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return -1; 353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (pid == 0) { 354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* child */ 355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char* argv[4] = { "/bin/sh", "-c", cmd, 0 }; 356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(execv)(argv[0], argv); 357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* If we're still alive here, execve failed. */ 359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(exit)(1); 360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* parent */ 362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* We have to set SIGCHLD to its default behaviour in order that 363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(waitpid) works (at least on AIX). According to the Linux 364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown man page for waitpid: 365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown POSIX.1-2001 specifies that if the disposition of SIGCHLD is 367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set to SIG_IGN or the SA_NOCLDWAIT flag is set for SIGCHLD 368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (see sigaction(2)), then children that terminate do not 369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown become zombies and a call to wait() or waitpid() will block 370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown until all children have terminated, and then fail with errno 371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown set to ECHILD. (The original POSIX standard left the 372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown behaviour of setting SIGCHLD to SIG_IGN unspecified.) 373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int ir, zzz; 375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigaction_toK_t sa, sa2; 376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vki_sigaction_fromK_t saved_sa; 377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)( &sa, 0, sizeof(sa) ); 378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(sigemptyset)(&sa.sa_mask); 379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sa.ksa_handler = VKI_SIG_DFL; 380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sa.sa_flags = 0; 381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ir = VG_(sigaction)(VKI_SIGCHLD, &sa, &saved_sa); 382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(ir == 0); 383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown zzz = VG_(waitpid)(pid, NULL, 0); 385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(convert_sigaction_fromK_to_toK)( &saved_sa, &sa2 ); 387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ir = VG_(sigaction)(VKI_SIGCHLD, &sa2, NULL); 388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(ir == 0); 389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return zzz == -1 ? -1 : 0; 390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Resource limits 395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Support for getrlimit. */ 398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(getrlimit) (Int resource, struct vki_rlimit *rlim) 399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res = VG_(mk_SysRes_Error)(VKI_ENOSYS); 401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* res = getrlimit( resource, rlim ); */ 402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# ifdef __NR_ugetrlimit 403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall2)(__NR_ugetrlimit, resource, (UWord)rlim); 404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sr_isError(res) && sr_Err(res) == VKI_ENOSYS) 406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall2)(__NR_getrlimit, resource, (UWord)rlim); 407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? -1 : sr_Res(res); 408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Support for setrlimit. */ 412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(setrlimit) (Int resource, const struct vki_rlimit *rlim) 413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* res = setrlimit( resource, rlim ); */ 416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall2)(__NR_setrlimit, resource, (UWord)rlim); 417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_isError(res) ? -1 : sr_Res(res); 418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 420b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Support for prctl. */ 421b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovInt VG_(prctl) (Int option, 422b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ULong arg2, ULong arg3, ULong arg4, ULong arg5) 423b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{ 424b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov SysRes res = VG_(mk_SysRes_Error)(VKI_ENOSYS); 425b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if defined(VGO_linux) 426b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* res = prctl( option, arg2, arg3, arg4, arg5 ); */ 427b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov res = VG_(do_syscall5)(__NR_prctl, (UWord) option, 428b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (UWord) arg2, (UWord) arg3, (UWord) arg4, 429b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (UWord) arg5); 430b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# endif 431b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 432b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return sr_isError(res) ? -1 : sr_Res(res); 433b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} 434b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pids, etc 437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(gettid)(void) 440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGO_linux) 442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res = VG_(do_syscall0)(__NR_gettid); 443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sr_isError(res) && sr_Res(res) == VKI_ENOSYS) { 445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char pid[16]; 446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * The gettid system call does not exist. The obvious assumption 448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * to make at this point would be that we are running on an older 449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * system where the getpid system call actually returns the ID of 450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * the current thread. 451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * 452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Unfortunately it seems that there are some systems with a kernel 453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * where getpid has been changed to return the ID of the thread group 454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * leader but where the gettid system call has not yet been added. 455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * 456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * So instead of calling getpid here we use readlink to see where 457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * the /proc/self link is pointing... 458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall3)(__NR_readlink, (UWord)"/proc/self", 461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (UWord)pid, sizeof(pid)); 462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!sr_isError(res) && sr_Res(res) > 0) { 463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Char* s; 464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pid[sr_Res(res)] = '\0'; 465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(mk_SysRes_Success)( VG_(strtoll10)(pid, &s) ); 466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (*s != '\0') { 467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_DebugMsg, 468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Warning: invalid file name linked to by /proc/self: %s\n", 469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pid); 470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_Res(res); 475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGO_darwin) 477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Darwin's gettid syscall is something else. 478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Use Mach thread ports for lwpid instead. 479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return mach_thread_self(); 480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unknown OS" 483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* You'd be amazed how many places need to know the current pid. */ 487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(getpid) ( void ) 488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* ASSUMES SYSCALL ALWAYS SUCCEEDS */ 490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_Res( VG_(do_syscall0)(__NR_getpid) ); 491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(getpgrp) ( void ) 494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* ASSUMES SYSCALL ALWAYS SUCCEEDS */ 496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_Res( VG_(do_syscall0)(__NR_getpgrp) ); 497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(getppid) ( void ) 500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* ASSUMES SYSCALL ALWAYS SUCCEEDS */ 502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_Res( VG_(do_syscall0)(__NR_getppid) ); 503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(geteuid) ( void ) 506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* ASSUMES SYSCALL ALWAYS SUCCEEDS */ 508b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if defined(__NR_geteuid32) 509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // We use the 32-bit version if it's supported. Otherwise, IDs greater 510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // than 65536 cause problems, as bug #151209 showed. 511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_Res( VG_(do_syscall0)(__NR_geteuid32) ); 512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_Res( VG_(do_syscall0)(__NR_geteuid) ); 514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(getegid) ( void ) 518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* ASSUMES SYSCALL ALWAYS SUCCEEDS */ 520b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if defined(__NR_getegid32) 521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // We use the 32-bit version if it's supported. Otherwise, IDs greater 522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // than 65536 cause problems, as bug #151209 showed. 523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_Res( VG_(do_syscall0)(__NR_getegid32) ); 524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_Res( VG_(do_syscall0)(__NR_getegid) ); 526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Get supplementary groups into list[0 .. size-1]. Returns the 530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown number of groups written, or -1 if error. Note that in order to be 531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown portable, the groups are 32-bit unsigned ints regardless of the 532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown platform. */ 533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(getgroups)( Int size, UInt* list ) 534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) 536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i; 537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes sres; 538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UShort list16[64]; 539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (size < 0) return -1; 540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (size > 64) size = 64; 541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sres = VG_(do_syscall2)(__NR_getgroups, size, (Addr)list16); 542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sr_isError(sres)) 543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return -1; 544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sr_Res(sres) > size) 545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return -1; 546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < sr_Res(sres); i++) 547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown list[i] = (UInt)list16[i]; 548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_Res(sres); 549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGP_amd64_linux) || defined(VGP_ppc64_linux) \ 551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown || defined(VGP_arm_linux) \ 552663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng || defined(VGO_darwin) || defined(VGP_s390x_linux) \ 553663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng || defined(VGP_mips32_linux) 554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes sres; 555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sres = VG_(do_syscall2)(__NR_getgroups, size, (Addr)list); 556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sr_isError(sres)) 557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return -1; 558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_Res(sres); 559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "VG_(getgroups): needs implementation on this platform" 562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Process tracing 567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(ptrace) ( Int request, Int pid, void *addr, void *data ) 570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall4)(__NR_ptrace, request, pid, (UWord)addr, (UWord)data); 573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sr_isError(res)) 574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return -1; 575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_Res(res); 576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Fork 580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt VG_(fork) ( void ) 583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 584b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov# if defined(VGO_linux) 585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall0)(__NR_fork); 587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sr_isError(res)) 588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return -1; 589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_Res(res); 590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGO_darwin) 592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SysRes res; 593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall0)(__NR_fork); /* __NR_fork is UX64 */ 594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sr_isError(res)) 595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return -1; 596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* on success: wLO = child pid; wHI = 1 for child, 0 for parent */ 597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sr_ResHI(res) != 0) { 598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; /* this is child: return 0 instead of child pid */ 599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return sr_Res(res); 601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unknown OS" 604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Timing stuff 609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownUInt VG_(read_millisecond_timer) ( void ) 612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* 'now' and 'base' are in microseconds */ 614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static ULong base = 0; 615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong now; 616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# if defined(VGO_linux) 618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { SysRes res; 619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_timespec ts_now; 620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall2)(__NR_clock_gettime, VKI_CLOCK_MONOTONIC, 621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (UWord)&ts_now); 622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (sr_isError(res) == 0) { 623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown now = ts_now.tv_sec * 1000000ULL + ts_now.tv_nsec / 1000; 624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_timeval tv_now; 626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall2)(__NR_gettimeofday, (UWord)&tv_now, (UWord)NULL); 627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(! sr_isError(res)); 628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown now = tv_now.tv_sec * 1000000ULL + tv_now.tv_usec; 629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# elif defined(VGO_darwin) 633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Weird: it seems that gettimeofday() doesn't fill in the timeval, but 634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // rather returns the tv_sec as the low 32 bits of the result and the 635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // tv_usec as the high 32 bits of the result. (But the timeval cannot be 636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // NULL!) See bug 200990. 637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { SysRes res; 638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown struct vki_timeval tv_now = { 0, 0 }; 639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown res = VG_(do_syscall2)(__NR_gettimeofday, (UWord)&tv_now, (UWord)NULL); 640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_assert(! sr_isError(res)); 641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown now = sr_Res(res) * 1000000ULL + sr_ResHI(res); 642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# else 645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# error "Unknown OS" 646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# endif 647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* COMMON CODE */ 649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (base == 0) 650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown base = now; 651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return (now - base) / 1000; 653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* --------------------------------------------------------------------- 657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown atfork() 658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ------------------------------------------------------------------ */ 659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstruct atfork { 661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_atfork_t pre; 662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_atfork_t parent; 663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown vg_atfork_t child; 664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}; 665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define VG_MAX_ATFORK 10 667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic struct atfork atforks[VG_MAX_ATFORK]; 669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int n_atfork = 0; 670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(atfork)(vg_atfork_t pre, vg_atfork_t parent, vg_atfork_t child) 672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i; 674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < n_atfork; i++) { 676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (atforks[i].pre == pre && 677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown atforks[i].parent == parent && 678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown atforks[i].child == child) 679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n_atfork >= VG_MAX_ATFORK) 683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(core_panic)( 684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Too many VG_(atfork) handlers requested: raise VG_MAX_ATFORK"); 685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown atforks[n_atfork].pre = pre; 687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown atforks[n_atfork].parent = parent; 688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown atforks[n_atfork].child = child; 689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_atfork++; 691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(do_atfork_pre)(ThreadId tid) 694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i; 696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < n_atfork; i++) 698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (atforks[i].pre != NULL) 699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (*atforks[i].pre)(tid); 700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(do_atfork_parent)(ThreadId tid) 703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Int i; 705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < n_atfork; i++) 707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (atforks[i].parent != NULL) 708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (*atforks[i].parent)(tid); 709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 711663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengvoid VG_(do_atfork_child)(ThreadId tid) 712663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{ 713663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Int i; 714f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov 715663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng for (i = 0; i < n_atfork; i++) 716663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (atforks[i].child != NULL) 717663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng (*atforks[i].child)(tid); 718663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng} 719f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov 720663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 721663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* --------------------------------------------------------------------- 722663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng icache invalidation 723663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng ------------------------------------------------------------------ */ 724663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 725663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengvoid VG_(invalidate_icache) ( void *ptr, SizeT nbytes ) 726f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov{ 727663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# if defined(VGA_ppc32) || defined(VGA_ppc64) 728663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Addr startaddr = (Addr) ptr; 729663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Addr endaddr = startaddr + nbytes; 730663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Addr cls; 731663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Addr addr; 732663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VexArchInfo vai; 733f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov 734663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng if (nbytes == 0) return; 735663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert(nbytes > 0); 736f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov 737663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(machine_get_VexArchInfo)( NULL, &vai ); 738663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng cls = vai.ppc_cache_line_szB; 739663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 740663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* Stay sane .. */ 741663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert(cls == 32 || cls == 64 || cls == 128); 742663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 743663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng startaddr &= ~(cls - 1); 744663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng for (addr = startaddr; addr < endaddr; addr += cls) { 745663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng __asm__ __volatile__("dcbst 0,%0" : : "r" (addr)); 746f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov } 747663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng __asm__ __volatile__("sync"); 748663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng for (addr = startaddr; addr < endaddr; addr += cls) { 749663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng __asm__ __volatile__("icbi 0,%0" : : "r" (addr)); 750663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng } 751663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng __asm__ __volatile__("sync; isync"); 752f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov 753663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# elif defined(VGA_x86) 754663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* no need to do anything, hardware provides coherence */ 755f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov 756663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# elif defined(VGA_amd64) 757663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* no need to do anything, hardware provides coherence */ 758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 759663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# elif defined(VGA_s390x) 760663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* no need to do anything, hardware provides coherence */ 761f0cb39bc6abe181a0abdd1f6c778521ae8497277Evgeniy Stepanov 762663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# elif defined(VGP_arm_linux) 763663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng /* ARM cache flushes are privileged, so we must defer to the kernel. */ 764663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Addr startaddr = (Addr) ptr; 765663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng Addr endaddr = startaddr + nbytes; 766663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng VG_(do_syscall2)(__NR_ARM_cacheflush, startaddr, endaddr); 767663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 768663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# elif defined(VGA_mips32) 769663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng SysRes sres = VG_(do_syscall3)(__NR_cacheflush, (UWord) ptr, 770663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng (UWord) nbytes, (UWord) 3); 771663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng vg_assert( sres._isError == 0 ); 772663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng 773663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# else 774663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# error "Unknown ARCH" 775663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng# endif 776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end ---*/ 781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 782