blob: 61441d7d346c4d3b7aed64a62249c1651b911f11 [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
njnf39e9a32005-06-12 02:43:17 +00003/*--- Process-related libc stuff. m_libcproc.c ---*/
sewardjde4a1d02002-03-22 01:27:54 +00004/*--------------------------------------------------------------------*/
njned6b8242005-06-01 00:03:17 +00005
sewardjde4a1d02002-03-22 01:27:54 +00006/*
njnb9c427c2004-12-01 14:14:42 +00007 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
sewardjde4a1d02002-03-22 01:27:54 +00009
sewardj9eecbbb2010-05-03 21:37:12 +000010 Copyright (C) 2000-2010 Julian Seward
sewardjde4a1d02002-03-22 01:27:54 +000011 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000012
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
njn25e49d8e72002-09-23 09:36:25 +000028 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000029*/
30
njnc7561b92005-06-19 01:24:32 +000031#include "pub_core_basics.h"
sewardj4cfea4f2006-10-14 19:26:10 +000032#include "pub_core_vki.h"
sewardjd470bfc2006-10-17 02:16:44 +000033#include "pub_core_vkiscnums.h"
njn97405b22005-06-02 03:39:33 +000034#include "pub_core_libcbase.h"
njn132bfcc2005-06-04 19:16:06 +000035#include "pub_core_libcassert.h"
njn36a20fa2005-06-03 03:08:39 +000036#include "pub_core_libcprint.h"
njnf39e9a32005-06-12 02:43:17 +000037#include "pub_core_libcproc.h"
sewardjd470bfc2006-10-17 02:16:44 +000038#include "pub_core_libcsignal.h"
sewardjd7a02db2008-12-12 08:07:49 +000039#include "pub_core_seqmatch.h"
njnaf1d7df2005-06-11 01:31:52 +000040#include "pub_core_mallocfree.h"
njn9abd6082005-06-17 21:31:45 +000041#include "pub_core_syscall.h"
sewardj14c7cc52007-02-25 15:08:24 +000042#include "pub_core_xarray.h"
sewardj45f4e7c2005-09-27 19:20:21 +000043#include "pub_core_clientstate.h"
sewardj1cf558c2005-04-25 01:36:56 +000044
njnf76d27a2009-05-28 01:53:07 +000045#if defined(VGO_darwin)
46/* --- !!! --- EXTERNAL HEADERS start --- !!! --- */
47#include <mach/mach.h> /* mach_thread_self */
48/* --- !!! --- EXTERNAL HEADERS end --- !!! --- */
49#endif
50
51/* IMPORTANT: on Darwin it is essential to use the _nocancel versions
52 of syscalls rather than the vanilla version, if a _nocancel version
53 is available. See docs/internals/Darwin-notes.txt for the reason
54 why. */
55
njnf39e9a32005-06-12 02:43:17 +000056/* ---------------------------------------------------------------------
57 Command line and environment stuff
58 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +000059
njnf39e9a32005-06-12 02:43:17 +000060/* As deduced from sp_at_startup, the client's argc, argv[] and
61 envp[] as extracted from the client's stack at startup-time. */
sewardj198f34f2007-07-09 23:13:07 +000062Char** VG_(client_envp) = NULL;
njnf39e9a32005-06-12 02:43:17 +000063
njn8d9965c2005-06-12 17:47:24 +000064/* Path to library directory */
65const Char *VG_(libdir) = VG_LIBDIR;
66
njne323a6b2010-07-01 02:35:03 +000067const Char *VG_(LD_PRELOAD_var_name) =
68#if defined(VGO_linux) || defined(VGO_aix5)
69 "LD_PRELOAD";
70#elif defined(VGO_darwin)
71 "DYLD_INSERT_LIBRARIES";
72#else
73# error Unknown OS
74#endif
75
njnf39e9a32005-06-12 02:43:17 +000076/* We do getenv without libc's help by snooping around in
77 VG_(client_envp) as determined at startup time. */
78Char *VG_(getenv)(Char *varname)
jsgf855d93d2003-10-13 22:26:55 +000079{
njnf39e9a32005-06-12 02:43:17 +000080 Int i, n;
sewardj198f34f2007-07-09 23:13:07 +000081 vg_assert( VG_(client_envp) );
njnf39e9a32005-06-12 02:43:17 +000082 n = VG_(strlen)(varname);
83 for (i = 0; VG_(client_envp)[i] != NULL; i++) {
84 Char* s = VG_(client_envp)[i];
85 if (VG_(strncmp)(varname, s, n) == 0 && s[n] == '=') {
86 return & s[n+1];
thughes8ef6d962004-10-16 10:46:01 +000087 }
88 }
njnf39e9a32005-06-12 02:43:17 +000089 return NULL;
nethercoteff9721d2004-01-26 17:10:01 +000090}
91
fitzhardinge98abfc72003-12-16 02:05:15 +000092void VG_(env_unsetenv) ( Char **env, const Char *varname )
93{
94 Char **from;
95 Char **to = NULL;
96 Int len = VG_(strlen)(varname);
97
sewardj45f4e7c2005-09-27 19:20:21 +000098 for (from = to = env; from && *from; from++) {
fitzhardinge98abfc72003-12-16 02:05:15 +000099 if (!(VG_(strncmp)(varname, *from, len) == 0 && (*from)[len] == '=')) {
100 *to = *from;
101 to++;
102 }
103 }
104 *to = *from;
105}
106
107/* set the environment; returns the old env if a new one was allocated */
108Char **VG_(env_setenv) ( Char ***envp, const Char* varname, const Char *val )
109{
110 Char **env = (*envp);
111 Char **cpp;
112 Int len = VG_(strlen)(varname);
sewardj9c606bd2008-09-18 18:12:50 +0000113 Char *valstr = VG_(arena_malloc)(VG_AR_CORE, "libcproc.es.1",
114 len + VG_(strlen)(val) + 2);
fitzhardinge98abfc72003-12-16 02:05:15 +0000115 Char **oldenv = NULL;
116
117 VG_(sprintf)(valstr, "%s=%s", varname, val);
118
sewardj45f4e7c2005-09-27 19:20:21 +0000119 for (cpp = env; cpp && *cpp; cpp++) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000120 if (VG_(strncmp)(varname, *cpp, len) == 0 && (*cpp)[len] == '=') {
121 *cpp = valstr;
122 return oldenv;
123 }
124 }
125
126 if (env == NULL) {
sewardj9c606bd2008-09-18 18:12:50 +0000127 env = VG_(arena_malloc)(VG_AR_CORE, "libcproc.es.2", sizeof(Char **) * 2);
fitzhardinge98abfc72003-12-16 02:05:15 +0000128 env[0] = valstr;
129 env[1] = NULL;
130
131 *envp = env;
132
133 } else {
134 Int envlen = (cpp-env) + 2;
sewardj9c606bd2008-09-18 18:12:50 +0000135 Char **newenv = VG_(arena_malloc)(VG_AR_CORE, "libcproc.es.3",
136 envlen * sizeof(Char **));
fitzhardinge98abfc72003-12-16 02:05:15 +0000137
sewardj45f4e7c2005-09-27 19:20:21 +0000138 for (cpp = newenv; *env; )
fitzhardinge98abfc72003-12-16 02:05:15 +0000139 *cpp++ = *env++;
140 *cpp++ = valstr;
141 *cpp++ = NULL;
142
143 oldenv = *envp;
144
145 *envp = newenv;
146 }
147
148 return oldenv;
149}
150
njncda2f0f2009-05-18 02:12:08 +0000151
nethercote60a96c52004-08-03 13:08:31 +0000152/* Walk through a colon-separated environment variable, and remove the
153 entries which match remove_pattern. It slides everything down over
154 the removed entries, and pads the remaining space with '\0'. It
155 modifies the entries in place (in the client address space), but it
156 shouldn't matter too much, since we only do this just before an
157 execve().
158
159 This is also careful to mop up any excess ':'s, since empty strings
160 delimited by ':' are considered to be '.' in a path.
161*/
162static void mash_colon_env(Char *varp, const Char *remove_pattern)
163{
164 Char *const start = varp;
165 Char *entry_start = varp;
166 Char *output = varp;
167
168 if (varp == NULL)
169 return;
170
171 while(*varp) {
172 if (*varp == ':') {
173 Char prev;
174 Bool match;
175
176 /* This is a bit subtle: we want to match against the entry
177 we just copied, because it may have overlapped with
178 itself, junking the original. */
179
180 prev = *output;
181 *output = '\0';
182
183 match = VG_(string_match)(remove_pattern, entry_start);
184
185 *output = prev;
186
187 if (match) {
188 output = entry_start;
189 varp++; /* skip ':' after removed entry */
190 } else
191 entry_start = output+1; /* entry starts after ':' */
192 }
193
tom149ede92010-06-15 12:49:07 +0000194 if (*varp)
195 *output++ = *varp++;
nethercote60a96c52004-08-03 13:08:31 +0000196 }
197
tom149ede92010-06-15 12:49:07 +0000198 /* make sure last entry is nul terminated */
199 *output = '\0';
200
nethercote60a96c52004-08-03 13:08:31 +0000201 /* match against the last entry */
202 if (VG_(string_match)(remove_pattern, entry_start)) {
203 output = entry_start;
204 if (output > start) {
205 /* remove trailing ':' */
206 output--;
207 vg_assert(*output == ':');
208 }
209 }
210
211 /* pad out the left-overs with '\0' */
212 while(output < varp)
213 *output++ = '\0';
214}
215
216
217// Removes all the Valgrind-added stuff from the passed environment. Used
218// when starting child processes, so they don't see that added stuff.
219void VG_(env_remove_valgrind_env_stuff)(Char** envp)
220{
njnf76d27a2009-05-28 01:53:07 +0000221
222#if defined(VGO_darwin)
223
224 // Environment cleanup is also handled during parent launch
225 // in vg_preloaded.c:vg_cleanup_env().
226
227#endif
228
nethercote60a96c52004-08-03 13:08:31 +0000229 Int i;
230 Char* ld_preload_str = NULL;
231 Char* ld_library_path_str = NULL;
njnf76d27a2009-05-28 01:53:07 +0000232 Char* dyld_insert_libraries_str = NULL;
nethercote60a96c52004-08-03 13:08:31 +0000233 Char* buf;
234
235 // Find LD_* variables
njnf76d27a2009-05-28 01:53:07 +0000236 // DDD: should probably conditionally compiled some of this:
237 // - LD_LIBRARY_PATH is universal?
238 // - LD_PRELOAD is on Linux, not on Darwin, not sure about AIX
239 // - DYLD_INSERT_LIBRARIES and DYLD_SHARED_REGION are Darwin-only
nethercote60a96c52004-08-03 13:08:31 +0000240 for (i = 0; envp[i] != NULL; i++) {
241 if (VG_(strncmp)(envp[i], "LD_PRELOAD=", 11) == 0)
242 ld_preload_str = &envp[i][11];
243 if (VG_(strncmp)(envp[i], "LD_LIBRARY_PATH=", 16) == 0)
244 ld_library_path_str = &envp[i][16];
njnf76d27a2009-05-28 01:53:07 +0000245 if (VG_(strncmp)(envp[i], "DYLD_INSERT_LIBRARIES=", 22) == 0)
246 dyld_insert_libraries_str = &envp[i][22];
nethercote60a96c52004-08-03 13:08:31 +0000247 }
248
sewardj9c606bd2008-09-18 18:12:50 +0000249 buf = VG_(arena_malloc)(VG_AR_CORE, "libcproc.erves.1",
250 VG_(strlen)(VG_(libdir)) + 20);
nethercote60a96c52004-08-03 13:08:31 +0000251
252 // Remove Valgrind-specific entries from LD_*.
nethercote60a96c52004-08-03 13:08:31 +0000253 VG_(sprintf)(buf, "%s*/vgpreload_*.so", VG_(libdir));
254 mash_colon_env(ld_preload_str, buf);
njnf76d27a2009-05-28 01:53:07 +0000255 mash_colon_env(dyld_insert_libraries_str, buf);
nethercote60a96c52004-08-03 13:08:31 +0000256 VG_(sprintf)(buf, "%s*", VG_(libdir));
257 mash_colon_env(ld_library_path_str, buf);
258
sewardj45f4e7c2005-09-27 19:20:21 +0000259 // Remove VALGRIND_LAUNCHER variable.
260 VG_(env_unsetenv)(envp, VALGRIND_LAUNCHER);
nethercote60a96c52004-08-03 13:08:31 +0000261
njnf76d27a2009-05-28 01:53:07 +0000262 // Remove DYLD_SHARED_REGION variable.
263 VG_(env_unsetenv)(envp, "DYLD_SHARED_REGION");
264
nethercote60a96c52004-08-03 13:08:31 +0000265 // XXX if variable becomes empty, remove it completely?
266
267 VG_(arena_free)(VG_AR_CORE, buf);
268}
269
njnf39e9a32005-06-12 02:43:17 +0000270/* ---------------------------------------------------------------------
271 Various important syscall wrappers
272 ------------------------------------------------------------------ */
273
274Int VG_(waitpid)(Int pid, Int *status, Int options)
275{
sewardjd470bfc2006-10-17 02:16:44 +0000276# if defined(VGO_linux)
njnf76d27a2009-05-28 01:53:07 +0000277 SysRes res = VG_(do_syscall4)(__NR_wait4,
278 pid, (UWord)status, options, 0);
279 return sr_isError(res) ? -1 : sr_Res(res);
280# elif defined(VGO_darwin)
281 SysRes res = VG_(do_syscall4)(__NR_wait4_nocancel,
282 pid, (UWord)status, options, 0);
njncda2f0f2009-05-18 02:12:08 +0000283 return sr_isError(res) ? -1 : sr_Res(res);
sewardjd470bfc2006-10-17 02:16:44 +0000284# elif defined(VGO_aix5)
285 /* magic number 4 obtained by truss-ing a C program doing
286 'waitpid'. Note status and pid args opposite way round from
287 POSIX. */
288 SysRes res = VG_(do_syscall5)(__NR_AIX5_kwaitpid,
289 (UWord)status, pid, 4 | options,0,0);
njncda2f0f2009-05-18 02:12:08 +0000290 if (0) VG_(printf)("waitpid: got 0x%lx 0x%lx\n", sr_Res(res), res.err);
291 return sr_isError(res) ? -1 : sr_Res(res);
sewardjd470bfc2006-10-17 02:16:44 +0000292# else
293# error Unknown OS
294# endif
njnf39e9a32005-06-12 02:43:17 +0000295}
296
njnf39e9a32005-06-12 02:43:17 +0000297/* clone the environment */
tom4e136952005-07-18 14:02:11 +0000298Char **VG_(env_clone) ( Char **oldenv )
njnf39e9a32005-06-12 02:43:17 +0000299{
300 Char **oldenvp;
301 Char **newenvp;
302 Char **newenv;
303 Int envlen;
304
305 for (oldenvp = oldenv; oldenvp && *oldenvp; oldenvp++);
306
307 envlen = oldenvp - oldenv + 1;
308
sewardj9c606bd2008-09-18 18:12:50 +0000309 newenv = VG_(arena_malloc)(VG_AR_CORE, "libcproc.ec.1",
310 envlen * sizeof(Char **));
njnf39e9a32005-06-12 02:43:17 +0000311
312 oldenvp = oldenv;
313 newenvp = newenv;
314
315 while (oldenvp && *oldenvp) {
316 *newenvp++ = *oldenvp++;
317 }
318
319 *newenvp = *oldenvp;
320
321 return newenv;
322}
323
njne9ba34a2008-10-13 04:19:15 +0000324void VG_(execv) ( Char* filename, Char** argv )
325{
326 Char** envp;
327 SysRes res;
328
329 /* restore the DATA rlimit for the child */
330 VG_(setrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
331
332 envp = VG_(env_clone)(VG_(client_envp));
333 VG_(env_remove_valgrind_env_stuff)( envp );
334
335 res = VG_(do_syscall3)(__NR_execve,
336 (UWord)filename, (UWord)argv, (UWord)envp);
337
njncda2f0f2009-05-18 02:12:08 +0000338 VG_(printf)("EXEC failed, errno = %lld\n", (Long)sr_Err(res));
njne9ba34a2008-10-13 04:19:15 +0000339}
340
sewardje6a25242002-04-21 22:03:07 +0000341/* Return -1 if error, else 0. NOTE does not indicate return code of
342 child! */
343Int VG_(system) ( Char* cmd )
344{
njne9ba34a2008-10-13 04:19:15 +0000345 Int pid;
sewardje6a25242002-04-21 22:03:07 +0000346 if (cmd == NULL)
347 return 1;
njne9ba34a2008-10-13 04:19:15 +0000348 pid = VG_(fork)();
349 if (pid < 0)
sewardje6a25242002-04-21 22:03:07 +0000350 return -1;
351 if (pid == 0) {
352 /* child */
njne9ba34a2008-10-13 04:19:15 +0000353 Char* argv[4] = { "/bin/sh", "-c", cmd, 0 };
354 VG_(execv)(argv[0], argv);
nethercoteff9721d2004-01-26 17:10:01 +0000355
sewardje6a25242002-04-21 22:03:07 +0000356 /* If we're still alive here, execve failed. */
fitzhardingeabab8392004-03-02 21:38:51 +0000357 VG_(exit)(1);
sewardje6a25242002-04-21 22:03:07 +0000358 } else {
359 /* parent */
sewardjd470bfc2006-10-17 02:16:44 +0000360 /* We have to set SIGCHLD to its default behaviour in order that
361 VG_(waitpid) works (at least on AIX). According to the Linux
362 man page for waitpid:
363
364 POSIX.1-2001 specifies that if the disposition of SIGCHLD is
365 set to SIG_IGN or the SA_NOCLDWAIT flag is set for SIGCHLD
366 (see sigaction(2)), then children that terminate do not
367 become zombies and a call to wait() or waitpid() will block
368 until all children have terminated, and then fail with errno
369 set to ECHILD. (The original POSIX standard left the
370 behaviour of setting SIGCHLD to SIG_IGN unspecified.)
371 */
njncda2f0f2009-05-18 02:12:08 +0000372 Int ir, zzz;
373 vki_sigaction_toK_t sa, sa2;
374 vki_sigaction_fromK_t saved_sa;
375 VG_(memset)( &sa, 0, sizeof(sa) );
sewardjd470bfc2006-10-17 02:16:44 +0000376 VG_(sigemptyset)(&sa.sa_mask);
377 sa.ksa_handler = VKI_SIG_DFL;
378 sa.sa_flags = 0;
379 ir = VG_(sigaction)(VKI_SIGCHLD, &sa, &saved_sa);
380 vg_assert(ir == 0);
381
382 zzz = VG_(waitpid)(pid, NULL, 0);
383
njncda2f0f2009-05-18 02:12:08 +0000384 VG_(convert_sigaction_fromK_to_toK)( &saved_sa, &sa2 );
385 ir = VG_(sigaction)(VKI_SIGCHLD, &sa2, NULL);
sewardjd470bfc2006-10-17 02:16:44 +0000386 vg_assert(ir == 0);
sewardja8d8e232005-06-07 20:04:56 +0000387 return zzz == -1 ? -1 : 0;
sewardje6a25242002-04-21 22:03:07 +0000388 }
389}
390
njnf39e9a32005-06-12 02:43:17 +0000391/* ---------------------------------------------------------------------
392 Resource limits
393 ------------------------------------------------------------------ */
394
njnf39e9a32005-06-12 02:43:17 +0000395/* Support for getrlimit. */
396Int VG_(getrlimit) (Int resource, struct vki_rlimit *rlim)
397{
398 SysRes res = VG_(mk_SysRes_Error)(VKI_ENOSYS);
399 /* res = getrlimit( resource, rlim ); */
400# ifdef __NR_ugetrlimit
401 res = VG_(do_syscall2)(__NR_ugetrlimit, resource, (UWord)rlim);
402# endif
njncda2f0f2009-05-18 02:12:08 +0000403 if (sr_isError(res) && sr_Err(res) == VKI_ENOSYS)
njnf39e9a32005-06-12 02:43:17 +0000404 res = VG_(do_syscall2)(__NR_getrlimit, resource, (UWord)rlim);
njncda2f0f2009-05-18 02:12:08 +0000405 return sr_isError(res) ? -1 : sr_Res(res);
njnf39e9a32005-06-12 02:43:17 +0000406}
407
408
409/* Support for setrlimit. */
410Int VG_(setrlimit) (Int resource, const struct vki_rlimit *rlim)
411{
412 SysRes res;
413 /* res = setrlimit( resource, rlim ); */
414 res = VG_(do_syscall2)(__NR_setrlimit, resource, (UWord)rlim);
njncda2f0f2009-05-18 02:12:08 +0000415 return sr_isError(res) ? -1 : sr_Res(res);
njnf39e9a32005-06-12 02:43:17 +0000416}
sewardje6a25242002-04-21 22:03:07 +0000417
sewardjde4a1d02002-03-22 01:27:54 +0000418/* ---------------------------------------------------------------------
njnf39e9a32005-06-12 02:43:17 +0000419 pids, etc
420 ------------------------------------------------------------------ */
421
422Int VG_(gettid)(void)
423{
njncda2f0f2009-05-18 02:12:08 +0000424# if defined(VGO_linux)
njnf39e9a32005-06-12 02:43:17 +0000425 SysRes res = VG_(do_syscall0)(__NR_gettid);
426
njncda2f0f2009-05-18 02:12:08 +0000427 if (sr_isError(res) && sr_Res(res) == VKI_ENOSYS) {
njnf39e9a32005-06-12 02:43:17 +0000428 Char pid[16];
429 /*
430 * The gettid system call does not exist. The obvious assumption
431 * to make at this point would be that we are running on an older
432 * system where the getpid system call actually returns the ID of
433 * the current thread.
434 *
435 * Unfortunately it seems that there are some systems with a kernel
436 * where getpid has been changed to return the ID of the thread group
437 * leader but where the gettid system call has not yet been added.
438 *
439 * So instead of calling getpid here we use readlink to see where
440 * the /proc/self link is pointing...
441 */
442
443 res = VG_(do_syscall3)(__NR_readlink, (UWord)"/proc/self",
444 (UWord)pid, sizeof(pid));
njncda2f0f2009-05-18 02:12:08 +0000445 if (!sr_isError(res) && sr_Res(res) > 0) {
njn83df0b62009-02-25 01:01:05 +0000446 Char* s;
njncda2f0f2009-05-18 02:12:08 +0000447 pid[sr_Res(res)] = '\0';
448 res = VG_(mk_SysRes_Success)( VG_(strtoll10)(pid, &s) );
njn83df0b62009-02-25 01:01:05 +0000449 if (*s != '\0') {
450 VG_(message)(Vg_DebugMsg,
sewardj738856f2009-07-15 14:48:32 +0000451 "Warning: invalid file name linked to by /proc/self: %s\n",
452 pid);
njn83df0b62009-02-25 01:01:05 +0000453 }
njnf39e9a32005-06-12 02:43:17 +0000454 }
455 }
456
njncda2f0f2009-05-18 02:12:08 +0000457 return sr_Res(res);
458
459# elif defined(VGO_aix5)
460 SysRes res;
461 Int r;
462 vg_assert(__NR_AIX5__thread_self != __NR_AIX5_UNKNOWN);
463 res = VG_(do_syscall0)(__NR_AIX5__thread_self);
464 r = sr_Res(res);
465 return r;
466
njnf76d27a2009-05-28 01:53:07 +0000467# elif defined(VGO_darwin)
468 // Darwin's gettid syscall is something else.
469 // Use Mach thread ports for lwpid instead.
470 return mach_thread_self();
471
njncda2f0f2009-05-18 02:12:08 +0000472# else
473# error "Unknown OS"
sewardjd470bfc2006-10-17 02:16:44 +0000474# endif
njnf39e9a32005-06-12 02:43:17 +0000475}
476
477/* You'd be amazed how many places need to know the current pid. */
478Int VG_(getpid) ( void )
479{
480 /* ASSUMES SYSCALL ALWAYS SUCCEEDS */
njncda2f0f2009-05-18 02:12:08 +0000481 return sr_Res( VG_(do_syscall0)(__NR_getpid) );
njnf39e9a32005-06-12 02:43:17 +0000482}
483
484Int VG_(getpgrp) ( void )
485{
486 /* ASSUMES SYSCALL ALWAYS SUCCEEDS */
njncda2f0f2009-05-18 02:12:08 +0000487 return sr_Res( VG_(do_syscall0)(__NR_getpgrp) );
njnf39e9a32005-06-12 02:43:17 +0000488}
489
490Int VG_(getppid) ( void )
491{
492 /* ASSUMES SYSCALL ALWAYS SUCCEEDS */
njncda2f0f2009-05-18 02:12:08 +0000493 return sr_Res( VG_(do_syscall0)(__NR_getppid) );
njnf39e9a32005-06-12 02:43:17 +0000494}
495
sewardj45f4e7c2005-09-27 19:20:21 +0000496Int VG_(geteuid) ( void )
njnf39e9a32005-06-12 02:43:17 +0000497{
498 /* ASSUMES SYSCALL ALWAYS SUCCEEDS */
sewardjd470bfc2006-10-17 02:16:44 +0000499# if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
njncda2f0f2009-05-18 02:12:08 +0000500 return sr_Res( VG_(do_syscall1)(__NR_AIX5_getuidx, 1) );
tom8de3e812007-10-23 08:03:59 +0000501# elif defined(__NR_geteuid32)
njna8b1c482007-10-23 22:26:12 +0000502 // We use the 32-bit version if it's supported. Otherwise, IDs greater
503 // than 65536 cause problems, as bug #151209 showed.
njncda2f0f2009-05-18 02:12:08 +0000504 return sr_Res( VG_(do_syscall0)(__NR_geteuid32) );
sewardjd470bfc2006-10-17 02:16:44 +0000505# else
njncda2f0f2009-05-18 02:12:08 +0000506 return sr_Res( VG_(do_syscall0)(__NR_geteuid) );
sewardjd470bfc2006-10-17 02:16:44 +0000507# endif
sewardj45f4e7c2005-09-27 19:20:21 +0000508}
509
510Int VG_(getegid) ( void )
511{
512 /* ASSUMES SYSCALL ALWAYS SUCCEEDS */
sewardjd470bfc2006-10-17 02:16:44 +0000513# if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
njncda2f0f2009-05-18 02:12:08 +0000514 return sr_Res( VG_(do_syscall1)(__NR_AIX5_getgidx, 1) );
tom8de3e812007-10-23 08:03:59 +0000515# elif defined(__NR_getegid32)
njna8b1c482007-10-23 22:26:12 +0000516 // We use the 32-bit version if it's supported. Otherwise, IDs greater
517 // than 65536 cause problems, as bug #151209 showed.
njncda2f0f2009-05-18 02:12:08 +0000518 return sr_Res( VG_(do_syscall0)(__NR_getegid32) );
sewardjd470bfc2006-10-17 02:16:44 +0000519# else
njncda2f0f2009-05-18 02:12:08 +0000520 return sr_Res( VG_(do_syscall0)(__NR_getegid) );
sewardjd470bfc2006-10-17 02:16:44 +0000521# endif
sewardj45f4e7c2005-09-27 19:20:21 +0000522}
523
524/* Get supplementary groups into list[0 .. size-1]. Returns the
525 number of groups written, or -1 if error. Note that in order to be
526 portable, the groups are 32-bit unsigned ints regardless of the
527 platform. */
528Int VG_(getgroups)( Int size, UInt* list )
529{
sewardja48a4932005-09-29 11:09:56 +0000530# if defined(VGP_x86_linux) || defined(VGP_ppc32_linux)
sewardj45f4e7c2005-09-27 19:20:21 +0000531 Int i;
532 SysRes sres;
sewardj3ae3dd32005-12-27 02:08:03 +0000533 UShort list16[64];
sewardj45f4e7c2005-09-27 19:20:21 +0000534 if (size < 0) return -1;
sewardj3ae3dd32005-12-27 02:08:03 +0000535 if (size > 64) size = 64;
sewardj45f4e7c2005-09-27 19:20:21 +0000536 sres = VG_(do_syscall2)(__NR_getgroups, size, (Addr)list16);
njncda2f0f2009-05-18 02:12:08 +0000537 if (sr_isError(sres))
sewardj45f4e7c2005-09-27 19:20:21 +0000538 return -1;
njncda2f0f2009-05-18 02:12:08 +0000539 if (sr_Res(sres) > size)
sewardj45f4e7c2005-09-27 19:20:21 +0000540 return -1;
njncda2f0f2009-05-18 02:12:08 +0000541 for (i = 0; i < sr_Res(sres); i++)
sewardj45f4e7c2005-09-27 19:20:21 +0000542 list[i] = (UInt)list16[i];
njncda2f0f2009-05-18 02:12:08 +0000543 return sr_Res(sres);
sewardj45f4e7c2005-09-27 19:20:21 +0000544
sewardj59570ff2010-01-01 11:59:33 +0000545# elif defined(VGP_amd64_linux) || defined(VGP_ppc64_linux) \
546 || defined(VGP_arm_linux) \
njnf76d27a2009-05-28 01:53:07 +0000547 || defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5) \
548 || defined(VGO_darwin)
sewardj45f4e7c2005-09-27 19:20:21 +0000549 SysRes sres;
550 sres = VG_(do_syscall2)(__NR_getgroups, size, (Addr)list);
njncda2f0f2009-05-18 02:12:08 +0000551 if (sr_isError(sres))
sewardj45f4e7c2005-09-27 19:20:21 +0000552 return -1;
njncda2f0f2009-05-18 02:12:08 +0000553 return sr_Res(sres);
sewardj45f4e7c2005-09-27 19:20:21 +0000554
555# else
556# error "VG_(getgroups): needs implementation on this platform"
557# endif
558}
559
560/* ---------------------------------------------------------------------
561 Process tracing
562 ------------------------------------------------------------------ */
563
564Int VG_(ptrace) ( Int request, Int pid, void *addr, void *data )
565{
566 SysRes res;
567 res = VG_(do_syscall4)(__NR_ptrace, request, pid, (UWord)addr, (UWord)data);
njncda2f0f2009-05-18 02:12:08 +0000568 if (sr_isError(res))
sewardj45f4e7c2005-09-27 19:20:21 +0000569 return -1;
njncda2f0f2009-05-18 02:12:08 +0000570 return sr_Res(res);
sewardj45f4e7c2005-09-27 19:20:21 +0000571}
572
573/* ---------------------------------------------------------------------
574 Fork
575 ------------------------------------------------------------------ */
576
577Int VG_(fork) ( void )
578{
njncda2f0f2009-05-18 02:12:08 +0000579# if defined(VGO_linux) || defined(VGO_aix5)
sewardj45f4e7c2005-09-27 19:20:21 +0000580 SysRes res;
581 res = VG_(do_syscall0)(__NR_fork);
njncda2f0f2009-05-18 02:12:08 +0000582 if (sr_isError(res))
sewardj45f4e7c2005-09-27 19:20:21 +0000583 return -1;
njncda2f0f2009-05-18 02:12:08 +0000584 return sr_Res(res);
585
njnf76d27a2009-05-28 01:53:07 +0000586# elif defined(VGO_darwin)
587 SysRes res;
588 res = VG_(do_syscall0)(__NR_fork); /* __NR_fork is UX64 */
589 if (sr_isError(res))
590 return -1;
591 /* on success: wLO = child pid; wHI = 1 for child, 0 for parent */
592 if (sr_ResHI(res) != 0) {
593 return 0; /* this is child: return 0 instead of child pid */
594 }
595 return sr_Res(res);
596
njncda2f0f2009-05-18 02:12:08 +0000597# else
598# error "Unknown OS"
599# endif
njnf39e9a32005-06-12 02:43:17 +0000600}
601
602/* ---------------------------------------------------------------------
603 Timing stuff
sewardj5f07b662002-04-23 16:52:51 +0000604 ------------------------------------------------------------------ */
605
sewardj5f07b662002-04-23 16:52:51 +0000606UInt VG_(read_millisecond_timer) ( void )
607{
sewardjd470bfc2006-10-17 02:16:44 +0000608 /* 'now' and 'base' are in microseconds */
fitzhardinge426f9e62004-01-25 03:44:18 +0000609 static ULong base = 0;
sewardja8d8e232005-06-07 20:04:56 +0000610 ULong now;
sewardj5f07b662002-04-23 16:52:51 +0000611
njncda2f0f2009-05-18 02:12:08 +0000612# if defined(VGO_linux)
613 { SysRes res;
614 struct vki_timespec ts_now;
615 res = VG_(do_syscall2)(__NR_clock_gettime, VKI_CLOCK_MONOTONIC,
616 (UWord)&ts_now);
617 if (sr_isError(res) == 0) {
618 now = ts_now.tv_sec * 1000000ULL + ts_now.tv_nsec / 1000;
619 } else {
620 struct vki_timeval tv_now;
621 res = VG_(do_syscall2)(__NR_gettimeofday, (UWord)&tv_now, (UWord)NULL);
622 vg_assert(! sr_isError(res));
623 now = tv_now.tv_sec * 1000000ULL + tv_now.tv_usec;
624 }
625 }
626
627# elif defined(VGO_aix5)
sewardjd470bfc2006-10-17 02:16:44 +0000628 /* AIX requires a totally different implementation since
629 sys_gettimeofday doesn't exist. We use the POWER real-time
630 register facility. This will SIGILL on PowerPC 970 on AIX,
631 since PowerPC doesn't support these instructions. */
632 UWord nsec, sec1, sec2;
633 while (1) {
634 __asm__ __volatile__ ("\n"
635 "\tmfspr %0,4\n" /* 4==RTCU */
636 "\tmfspr %1,5\n" /* 5==RTCL */
637 "\tmfspr %2,4\n" /* 4==RTCU */
638 : "=b" (sec1), "=b" (nsec), "=b" (sec2)
639 );
640 if (sec1 == sec2) break;
641 }
642 vg_assert(nsec < 1000*1000*1000);
643 now = ((ULong)sec1) * 1000000ULL;
644 now += (ULong)(nsec / 1000);
sewardjd470bfc2006-10-17 02:16:44 +0000645
njnf76d27a2009-05-28 01:53:07 +0000646# elif defined(VGO_darwin)
njnbe7e31a2009-07-22 02:52:14 +0000647 // Weird: it seems that gettimeofday() doesn't fill in the timeval, but
648 // rather returns the tv_sec as the low 32 bits of the result and the
649 // tv_usec as the high 32 bits of the result. (But the timeval cannot be
650 // NULL!) See bug 200990.
njnf76d27a2009-05-28 01:53:07 +0000651 { SysRes res;
bart8f992592009-07-21 17:46:56 +0000652 struct vki_timeval tv_now = { 0, 0 };
njnf76d27a2009-05-28 01:53:07 +0000653 res = VG_(do_syscall2)(__NR_gettimeofday, (UWord)&tv_now, (UWord)NULL);
654 vg_assert(! sr_isError(res));
njnbe7e31a2009-07-22 02:52:14 +0000655 now = sr_Res(res) * 1000000ULL + sr_ResHI(res);
njnf76d27a2009-05-28 01:53:07 +0000656 }
657
njncda2f0f2009-05-18 02:12:08 +0000658# else
659# error "Unknown OS"
sewardjd470bfc2006-10-17 02:16:44 +0000660# endif
njncda2f0f2009-05-18 02:12:08 +0000661
662 /* COMMON CODE */
fitzhardinge66871692004-01-25 03:32:58 +0000663 if (base == 0)
664 base = now;
sewardj5f07b662002-04-23 16:52:51 +0000665
fitzhardinge66871692004-01-25 03:32:58 +0000666 return (now - base) / 1000;
sewardj5f07b662002-04-23 16:52:51 +0000667}
668
njncda2f0f2009-05-18 02:12:08 +0000669
sewardj5f07b662002-04-23 16:52:51 +0000670/* ---------------------------------------------------------------------
njne9ba34a2008-10-13 04:19:15 +0000671 atfork()
sewardja8d8e232005-06-07 20:04:56 +0000672 ------------------------------------------------------------------ */
673
njne9ba34a2008-10-13 04:19:15 +0000674struct atfork {
675 vg_atfork_t pre;
676 vg_atfork_t parent;
677 vg_atfork_t child;
678};
sewardja8d8e232005-06-07 20:04:56 +0000679
njne9ba34a2008-10-13 04:19:15 +0000680#define VG_MAX_ATFORK 10
sewardja8d8e232005-06-07 20:04:56 +0000681
njne9ba34a2008-10-13 04:19:15 +0000682static struct atfork atforks[VG_MAX_ATFORK];
683static Int n_atfork = 0;
684
685void VG_(atfork)(vg_atfork_t pre, vg_atfork_t parent, vg_atfork_t child)
sewardja8d8e232005-06-07 20:04:56 +0000686{
njne9ba34a2008-10-13 04:19:15 +0000687 Int i;
sewardja8d8e232005-06-07 20:04:56 +0000688
njne9ba34a2008-10-13 04:19:15 +0000689 for (i = 0; i < n_atfork; i++) {
690 if (atforks[i].pre == pre &&
691 atforks[i].parent == parent &&
692 atforks[i].child == child)
693 return;
694 }
695
696 if (n_atfork >= VG_MAX_ATFORK)
697 VG_(core_panic)(
698 "Too many VG_(atfork) handlers requested: raise VG_MAX_ATFORK");
699
700 atforks[n_atfork].pre = pre;
701 atforks[n_atfork].parent = parent;
702 atforks[n_atfork].child = child;
703
704 n_atfork++;
705}
706
707void VG_(do_atfork_pre)(ThreadId tid)
708{
709 Int i;
710
711 for (i = 0; i < n_atfork; i++)
712 if (atforks[i].pre != NULL)
713 (*atforks[i].pre)(tid);
714}
715
716void VG_(do_atfork_parent)(ThreadId tid)
717{
718 Int i;
719
720 for (i = 0; i < n_atfork; i++)
721 if (atforks[i].parent != NULL)
722 (*atforks[i].parent)(tid);
sewardja8d8e232005-06-07 20:04:56 +0000723}
724
725void VG_(do_atfork_child)(ThreadId tid)
726{
njne9ba34a2008-10-13 04:19:15 +0000727 Int i;
728
729 for (i = 0; i < n_atfork; i++)
730 if (atforks[i].child != NULL)
731 (*atforks[i].child)(tid);
sewardja8d8e232005-06-07 20:04:56 +0000732}
733
njnf76d27a2009-05-28 01:53:07 +0000734
sewardjde4a1d02002-03-22 01:27:54 +0000735/*--------------------------------------------------------------------*/
njnc6168192004-11-29 13:54:10 +0000736/*--- end ---*/
sewardjde4a1d02002-03-22 01:27:54 +0000737/*--------------------------------------------------------------------*/