blob: 9e4cd3e3ec46195c5149c66ec03f8f79de4bb94d [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
sewardj4d474d02008-02-11 11:34:59 +000010 Copyright (C) 2000-2008 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
njnf39e9a32005-06-12 02:43:17 +000045/* ---------------------------------------------------------------------
46 Command line and environment stuff
47 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +000048
njnf39e9a32005-06-12 02:43:17 +000049/* As deduced from sp_at_startup, the client's argc, argv[] and
50 envp[] as extracted from the client's stack at startup-time. */
sewardj198f34f2007-07-09 23:13:07 +000051Char** VG_(client_envp) = NULL;
njnf39e9a32005-06-12 02:43:17 +000052
njn8d9965c2005-06-12 17:47:24 +000053/* Path to library directory */
54const Char *VG_(libdir) = VG_LIBDIR;
55
njnf39e9a32005-06-12 02:43:17 +000056/* We do getenv without libc's help by snooping around in
57 VG_(client_envp) as determined at startup time. */
58Char *VG_(getenv)(Char *varname)
jsgf855d93d2003-10-13 22:26:55 +000059{
njnf39e9a32005-06-12 02:43:17 +000060 Int i, n;
sewardj198f34f2007-07-09 23:13:07 +000061 vg_assert( VG_(client_envp) );
njnf39e9a32005-06-12 02:43:17 +000062 n = VG_(strlen)(varname);
63 for (i = 0; VG_(client_envp)[i] != NULL; i++) {
64 Char* s = VG_(client_envp)[i];
65 if (VG_(strncmp)(varname, s, n) == 0 && s[n] == '=') {
66 return & s[n+1];
thughes8ef6d962004-10-16 10:46:01 +000067 }
68 }
njnf39e9a32005-06-12 02:43:17 +000069 return NULL;
nethercoteff9721d2004-01-26 17:10:01 +000070}
71
fitzhardinge98abfc72003-12-16 02:05:15 +000072void VG_(env_unsetenv) ( Char **env, const Char *varname )
73{
74 Char **from;
75 Char **to = NULL;
76 Int len = VG_(strlen)(varname);
77
sewardj45f4e7c2005-09-27 19:20:21 +000078 for (from = to = env; from && *from; from++) {
fitzhardinge98abfc72003-12-16 02:05:15 +000079 if (!(VG_(strncmp)(varname, *from, len) == 0 && (*from)[len] == '=')) {
80 *to = *from;
81 to++;
82 }
83 }
84 *to = *from;
85}
86
87/* set the environment; returns the old env if a new one was allocated */
88Char **VG_(env_setenv) ( Char ***envp, const Char* varname, const Char *val )
89{
90 Char **env = (*envp);
91 Char **cpp;
92 Int len = VG_(strlen)(varname);
sewardj9c606bd2008-09-18 18:12:50 +000093 Char *valstr = VG_(arena_malloc)(VG_AR_CORE, "libcproc.es.1",
94 len + VG_(strlen)(val) + 2);
fitzhardinge98abfc72003-12-16 02:05:15 +000095 Char **oldenv = NULL;
96
97 VG_(sprintf)(valstr, "%s=%s", varname, val);
98
sewardj45f4e7c2005-09-27 19:20:21 +000099 for (cpp = env; cpp && *cpp; cpp++) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000100 if (VG_(strncmp)(varname, *cpp, len) == 0 && (*cpp)[len] == '=') {
101 *cpp = valstr;
102 return oldenv;
103 }
104 }
105
106 if (env == NULL) {
sewardj9c606bd2008-09-18 18:12:50 +0000107 env = VG_(arena_malloc)(VG_AR_CORE, "libcproc.es.2", sizeof(Char **) * 2);
fitzhardinge98abfc72003-12-16 02:05:15 +0000108 env[0] = valstr;
109 env[1] = NULL;
110
111 *envp = env;
112
113 } else {
114 Int envlen = (cpp-env) + 2;
sewardj9c606bd2008-09-18 18:12:50 +0000115 Char **newenv = VG_(arena_malloc)(VG_AR_CORE, "libcproc.es.3",
116 envlen * sizeof(Char **));
fitzhardinge98abfc72003-12-16 02:05:15 +0000117
sewardj45f4e7c2005-09-27 19:20:21 +0000118 for (cpp = newenv; *env; )
fitzhardinge98abfc72003-12-16 02:05:15 +0000119 *cpp++ = *env++;
120 *cpp++ = valstr;
121 *cpp++ = NULL;
122
123 oldenv = *envp;
124
125 *envp = newenv;
126 }
127
128 return oldenv;
129}
130
nethercote60a96c52004-08-03 13:08:31 +0000131/* Walk through a colon-separated environment variable, and remove the
132 entries which match remove_pattern. It slides everything down over
133 the removed entries, and pads the remaining space with '\0'. It
134 modifies the entries in place (in the client address space), but it
135 shouldn't matter too much, since we only do this just before an
136 execve().
137
138 This is also careful to mop up any excess ':'s, since empty strings
139 delimited by ':' are considered to be '.' in a path.
140*/
141static void mash_colon_env(Char *varp, const Char *remove_pattern)
142{
143 Char *const start = varp;
144 Char *entry_start = varp;
145 Char *output = varp;
146
147 if (varp == NULL)
148 return;
149
150 while(*varp) {
151 if (*varp == ':') {
152 Char prev;
153 Bool match;
154
155 /* This is a bit subtle: we want to match against the entry
156 we just copied, because it may have overlapped with
157 itself, junking the original. */
158
159 prev = *output;
160 *output = '\0';
161
162 match = VG_(string_match)(remove_pattern, entry_start);
163
164 *output = prev;
165
166 if (match) {
167 output = entry_start;
168 varp++; /* skip ':' after removed entry */
169 } else
170 entry_start = output+1; /* entry starts after ':' */
171 }
172
173 *output++ = *varp++;
174 }
175
176 /* match against the last entry */
177 if (VG_(string_match)(remove_pattern, entry_start)) {
178 output = entry_start;
179 if (output > start) {
180 /* remove trailing ':' */
181 output--;
182 vg_assert(*output == ':');
183 }
184 }
185
186 /* pad out the left-overs with '\0' */
187 while(output < varp)
188 *output++ = '\0';
189}
190
191
192// Removes all the Valgrind-added stuff from the passed environment. Used
193// when starting child processes, so they don't see that added stuff.
194void VG_(env_remove_valgrind_env_stuff)(Char** envp)
195{
196 Int i;
197 Char* ld_preload_str = NULL;
198 Char* ld_library_path_str = NULL;
199 Char* buf;
200
201 // Find LD_* variables
202 for (i = 0; envp[i] != NULL; i++) {
203 if (VG_(strncmp)(envp[i], "LD_PRELOAD=", 11) == 0)
204 ld_preload_str = &envp[i][11];
205 if (VG_(strncmp)(envp[i], "LD_LIBRARY_PATH=", 16) == 0)
206 ld_library_path_str = &envp[i][16];
207 }
208
sewardj9c606bd2008-09-18 18:12:50 +0000209 buf = VG_(arena_malloc)(VG_AR_CORE, "libcproc.erves.1",
210 VG_(strlen)(VG_(libdir)) + 20);
nethercote60a96c52004-08-03 13:08:31 +0000211
212 // Remove Valgrind-specific entries from LD_*.
nethercote60a96c52004-08-03 13:08:31 +0000213 VG_(sprintf)(buf, "%s*/vgpreload_*.so", VG_(libdir));
214 mash_colon_env(ld_preload_str, buf);
215 VG_(sprintf)(buf, "%s*", VG_(libdir));
216 mash_colon_env(ld_library_path_str, buf);
217
sewardj45f4e7c2005-09-27 19:20:21 +0000218 // Remove VALGRIND_LAUNCHER variable.
219 VG_(env_unsetenv)(envp, VALGRIND_LAUNCHER);
nethercote60a96c52004-08-03 13:08:31 +0000220
221 // XXX if variable becomes empty, remove it completely?
222
223 VG_(arena_free)(VG_AR_CORE, buf);
224}
225
njnf39e9a32005-06-12 02:43:17 +0000226/* ---------------------------------------------------------------------
227 Various important syscall wrappers
228 ------------------------------------------------------------------ */
229
230Int VG_(waitpid)(Int pid, Int *status, Int options)
231{
sewardjd470bfc2006-10-17 02:16:44 +0000232# if defined(VGO_linux)
njnf39e9a32005-06-12 02:43:17 +0000233 SysRes res = VG_(do_syscall4)(__NR_wait4, pid, (UWord)status, options, 0);
sewardjd470bfc2006-10-17 02:16:44 +0000234 return res.isError ? -1 : res.res;
235# elif defined(VGO_aix5)
236 /* magic number 4 obtained by truss-ing a C program doing
237 'waitpid'. Note status and pid args opposite way round from
238 POSIX. */
239 SysRes res = VG_(do_syscall5)(__NR_AIX5_kwaitpid,
240 (UWord)status, pid, 4 | options,0,0);
sewardja8ffda62008-07-18 18:23:24 +0000241 if (0) VG_(printf)("waitpid: got 0x%lx 0x%lx\n", res.res, res.err);
sewardjd470bfc2006-10-17 02:16:44 +0000242 return res.isError ? -1 : res.res;
243# else
244# error Unknown OS
245# endif
njnf39e9a32005-06-12 02:43:17 +0000246}
247
njnf39e9a32005-06-12 02:43:17 +0000248/* clone the environment */
tom4e136952005-07-18 14:02:11 +0000249Char **VG_(env_clone) ( Char **oldenv )
njnf39e9a32005-06-12 02:43:17 +0000250{
251 Char **oldenvp;
252 Char **newenvp;
253 Char **newenv;
254 Int envlen;
255
256 for (oldenvp = oldenv; oldenvp && *oldenvp; oldenvp++);
257
258 envlen = oldenvp - oldenv + 1;
259
sewardj9c606bd2008-09-18 18:12:50 +0000260 newenv = VG_(arena_malloc)(VG_AR_CORE, "libcproc.ec.1",
261 envlen * sizeof(Char **));
njnf39e9a32005-06-12 02:43:17 +0000262
263 oldenvp = oldenv;
264 newenvp = newenv;
265
266 while (oldenvp && *oldenvp) {
267 *newenvp++ = *oldenvp++;
268 }
269
270 *newenvp = *oldenvp;
271
272 return newenv;
273}
274
njne9ba34a2008-10-13 04:19:15 +0000275void VG_(execv) ( Char* filename, Char** argv )
276{
277 Char** envp;
278 SysRes res;
279
280 /* restore the DATA rlimit for the child */
281 VG_(setrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
282
283 envp = VG_(env_clone)(VG_(client_envp));
284 VG_(env_remove_valgrind_env_stuff)( envp );
285
286 res = VG_(do_syscall3)(__NR_execve,
287 (UWord)filename, (UWord)argv, (UWord)envp);
288
289 VG_(printf)("EXEC failed, errno = %ld\n", res.res);
290}
291
sewardje6a25242002-04-21 22:03:07 +0000292/* Return -1 if error, else 0. NOTE does not indicate return code of
293 child! */
294Int VG_(system) ( Char* cmd )
295{
njne9ba34a2008-10-13 04:19:15 +0000296 Int pid;
sewardje6a25242002-04-21 22:03:07 +0000297 if (cmd == NULL)
298 return 1;
njne9ba34a2008-10-13 04:19:15 +0000299 pid = VG_(fork)();
300 if (pid < 0)
sewardje6a25242002-04-21 22:03:07 +0000301 return -1;
302 if (pid == 0) {
303 /* child */
njne9ba34a2008-10-13 04:19:15 +0000304 Char* argv[4] = { "/bin/sh", "-c", cmd, 0 };
305 VG_(execv)(argv[0], argv);
nethercoteff9721d2004-01-26 17:10:01 +0000306
sewardje6a25242002-04-21 22:03:07 +0000307 /* If we're still alive here, execve failed. */
fitzhardingeabab8392004-03-02 21:38:51 +0000308 VG_(exit)(1);
sewardje6a25242002-04-21 22:03:07 +0000309 } else {
310 /* parent */
sewardjd470bfc2006-10-17 02:16:44 +0000311 Int ir, zzz;
312 /* We have to set SIGCHLD to its default behaviour in order that
313 VG_(waitpid) works (at least on AIX). According to the Linux
314 man page for waitpid:
315
316 POSIX.1-2001 specifies that if the disposition of SIGCHLD is
317 set to SIG_IGN or the SA_NOCLDWAIT flag is set for SIGCHLD
318 (see sigaction(2)), then children that terminate do not
319 become zombies and a call to wait() or waitpid() will block
320 until all children have terminated, and then fail with errno
321 set to ECHILD. (The original POSIX standard left the
322 behaviour of setting SIGCHLD to SIG_IGN unspecified.)
323 */
324 struct vki_sigaction sa, saved_sa;
325 VG_(memset)( &sa, 0, sizeof(struct vki_sigaction) );
326 VG_(sigemptyset)(&sa.sa_mask);
327 sa.ksa_handler = VKI_SIG_DFL;
328 sa.sa_flags = 0;
329 ir = VG_(sigaction)(VKI_SIGCHLD, &sa, &saved_sa);
330 vg_assert(ir == 0);
331
332 zzz = VG_(waitpid)(pid, NULL, 0);
333
334 ir = VG_(sigaction)(VKI_SIGCHLD, &saved_sa, NULL);
335 vg_assert(ir == 0);
336
sewardja8d8e232005-06-07 20:04:56 +0000337 return zzz == -1 ? -1 : 0;
sewardje6a25242002-04-21 22:03:07 +0000338 }
339}
340
njnf39e9a32005-06-12 02:43:17 +0000341/* ---------------------------------------------------------------------
342 Resource limits
343 ------------------------------------------------------------------ */
344
njnf39e9a32005-06-12 02:43:17 +0000345/* Support for getrlimit. */
346Int VG_(getrlimit) (Int resource, struct vki_rlimit *rlim)
347{
348 SysRes res = VG_(mk_SysRes_Error)(VKI_ENOSYS);
349 /* res = getrlimit( resource, rlim ); */
350# ifdef __NR_ugetrlimit
351 res = VG_(do_syscall2)(__NR_ugetrlimit, resource, (UWord)rlim);
352# endif
sewardjd470bfc2006-10-17 02:16:44 +0000353 if (res.isError && res.err == VKI_ENOSYS)
njnf39e9a32005-06-12 02:43:17 +0000354 res = VG_(do_syscall2)(__NR_getrlimit, resource, (UWord)rlim);
sewardjd470bfc2006-10-17 02:16:44 +0000355 return res.isError ? -1 : res.res;
njnf39e9a32005-06-12 02:43:17 +0000356}
357
358
359/* Support for setrlimit. */
360Int VG_(setrlimit) (Int resource, const struct vki_rlimit *rlim)
361{
362 SysRes res;
363 /* res = setrlimit( resource, rlim ); */
364 res = VG_(do_syscall2)(__NR_setrlimit, resource, (UWord)rlim);
sewardjd470bfc2006-10-17 02:16:44 +0000365 return res.isError ? -1 : res.res;
njnf39e9a32005-06-12 02:43:17 +0000366}
sewardje6a25242002-04-21 22:03:07 +0000367
sewardjde4a1d02002-03-22 01:27:54 +0000368/* ---------------------------------------------------------------------
njnf39e9a32005-06-12 02:43:17 +0000369 pids, etc
370 ------------------------------------------------------------------ */
371
372Int VG_(gettid)(void)
373{
sewardjd470bfc2006-10-17 02:16:44 +0000374# if defined(VGO_aix5)
375 SysRes res;
376 Int r;
377 vg_assert(__NR_AIX5__thread_self != __NR_AIX5_UNKNOWN);
378 res = VG_(do_syscall0)(__NR_AIX5__thread_self);
379 r = res.res;
380 return r;
381
382# else
njnf39e9a32005-06-12 02:43:17 +0000383 SysRes res = VG_(do_syscall0)(__NR_gettid);
384
sewardjd470bfc2006-10-17 02:16:44 +0000385 if (res.isError && res.res == VKI_ENOSYS) {
njnf39e9a32005-06-12 02:43:17 +0000386 Char pid[16];
387 /*
388 * The gettid system call does not exist. The obvious assumption
389 * to make at this point would be that we are running on an older
390 * system where the getpid system call actually returns the ID of
391 * the current thread.
392 *
393 * Unfortunately it seems that there are some systems with a kernel
394 * where getpid has been changed to return the ID of the thread group
395 * leader but where the gettid system call has not yet been added.
396 *
397 * So instead of calling getpid here we use readlink to see where
398 * the /proc/self link is pointing...
399 */
400
401 res = VG_(do_syscall3)(__NR_readlink, (UWord)"/proc/self",
402 (UWord)pid, sizeof(pid));
sewardjd470bfc2006-10-17 02:16:44 +0000403 if (!res.isError && res.res > 0) {
404 pid[res.res] = '\0';
405 res.res = VG_(atoll)(pid);
njnf39e9a32005-06-12 02:43:17 +0000406 }
407 }
408
sewardjd470bfc2006-10-17 02:16:44 +0000409 return res.res;
410# endif
njnf39e9a32005-06-12 02:43:17 +0000411}
412
413/* You'd be amazed how many places need to know the current pid. */
414Int VG_(getpid) ( void )
415{
416 /* ASSUMES SYSCALL ALWAYS SUCCEEDS */
sewardjd470bfc2006-10-17 02:16:44 +0000417 return VG_(do_syscall0)(__NR_getpid) . res;
njnf39e9a32005-06-12 02:43:17 +0000418}
419
420Int VG_(getpgrp) ( void )
421{
422 /* ASSUMES SYSCALL ALWAYS SUCCEEDS */
sewardjd470bfc2006-10-17 02:16:44 +0000423 return VG_(do_syscall0)(__NR_getpgrp) . res;
njnf39e9a32005-06-12 02:43:17 +0000424}
425
426Int VG_(getppid) ( void )
427{
428 /* ASSUMES SYSCALL ALWAYS SUCCEEDS */
sewardjd470bfc2006-10-17 02:16:44 +0000429 return VG_(do_syscall0)(__NR_getppid) . res;
njnf39e9a32005-06-12 02:43:17 +0000430}
431
sewardj45f4e7c2005-09-27 19:20:21 +0000432Int VG_(geteuid) ( void )
njnf39e9a32005-06-12 02:43:17 +0000433{
434 /* ASSUMES SYSCALL ALWAYS SUCCEEDS */
sewardjd470bfc2006-10-17 02:16:44 +0000435# if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
436 return VG_(do_syscall1)(__NR_AIX5_getuidx, 1) . res;
tom8de3e812007-10-23 08:03:59 +0000437# elif defined(__NR_geteuid32)
njna8b1c482007-10-23 22:26:12 +0000438 // We use the 32-bit version if it's supported. Otherwise, IDs greater
439 // than 65536 cause problems, as bug #151209 showed.
tom8de3e812007-10-23 08:03:59 +0000440 return VG_(do_syscall0)(__NR_geteuid32) . res;
sewardjd470bfc2006-10-17 02:16:44 +0000441# else
442 return VG_(do_syscall0)(__NR_geteuid) . res;
443# endif
sewardj45f4e7c2005-09-27 19:20:21 +0000444}
445
446Int VG_(getegid) ( void )
447{
448 /* ASSUMES SYSCALL ALWAYS SUCCEEDS */
sewardjd470bfc2006-10-17 02:16:44 +0000449# if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
450 return VG_(do_syscall1)(__NR_AIX5_getgidx, 1) . res;
tom8de3e812007-10-23 08:03:59 +0000451# elif defined(__NR_getegid32)
njna8b1c482007-10-23 22:26:12 +0000452 // We use the 32-bit version if it's supported. Otherwise, IDs greater
453 // than 65536 cause problems, as bug #151209 showed.
tom8de3e812007-10-23 08:03:59 +0000454 return VG_(do_syscall0)(__NR_getegid32) . res;
sewardjd470bfc2006-10-17 02:16:44 +0000455# else
456 return VG_(do_syscall0)(__NR_getegid) . res;
457# endif
sewardj45f4e7c2005-09-27 19:20:21 +0000458}
459
460/* Get supplementary groups into list[0 .. size-1]. Returns the
461 number of groups written, or -1 if error. Note that in order to be
462 portable, the groups are 32-bit unsigned ints regardless of the
463 platform. */
464Int VG_(getgroups)( Int size, UInt* list )
465{
sewardja48a4932005-09-29 11:09:56 +0000466# if defined(VGP_x86_linux) || defined(VGP_ppc32_linux)
sewardj45f4e7c2005-09-27 19:20:21 +0000467 Int i;
468 SysRes sres;
sewardj3ae3dd32005-12-27 02:08:03 +0000469 UShort list16[64];
sewardj45f4e7c2005-09-27 19:20:21 +0000470 if (size < 0) return -1;
sewardj3ae3dd32005-12-27 02:08:03 +0000471 if (size > 64) size = 64;
sewardj45f4e7c2005-09-27 19:20:21 +0000472 sres = VG_(do_syscall2)(__NR_getgroups, size, (Addr)list16);
473 if (sres.isError)
474 return -1;
sewardjd470bfc2006-10-17 02:16:44 +0000475 if (sres.res > size)
sewardj45f4e7c2005-09-27 19:20:21 +0000476 return -1;
sewardjd470bfc2006-10-17 02:16:44 +0000477 for (i = 0; i < sres.res; i++)
sewardj45f4e7c2005-09-27 19:20:21 +0000478 list[i] = (UInt)list16[i];
sewardjd470bfc2006-10-17 02:16:44 +0000479 return sres.res;
sewardj45f4e7c2005-09-27 19:20:21 +0000480
sewardjd470bfc2006-10-17 02:16:44 +0000481# elif defined(VGP_amd64_linux) || defined(VGP_ppc64_linux) \
482 || defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
sewardj45f4e7c2005-09-27 19:20:21 +0000483 SysRes sres;
484 sres = VG_(do_syscall2)(__NR_getgroups, size, (Addr)list);
485 if (sres.isError)
486 return -1;
sewardjd470bfc2006-10-17 02:16:44 +0000487 return sres.res;
sewardj45f4e7c2005-09-27 19:20:21 +0000488
489# else
490# error "VG_(getgroups): needs implementation on this platform"
491# endif
492}
493
494/* ---------------------------------------------------------------------
495 Process tracing
496 ------------------------------------------------------------------ */
497
498Int VG_(ptrace) ( Int request, Int pid, void *addr, void *data )
499{
500 SysRes res;
501 res = VG_(do_syscall4)(__NR_ptrace, request, pid, (UWord)addr, (UWord)data);
502 if (res.isError)
503 return -1;
sewardjd470bfc2006-10-17 02:16:44 +0000504 return res.res;
sewardj45f4e7c2005-09-27 19:20:21 +0000505}
506
507/* ---------------------------------------------------------------------
508 Fork
509 ------------------------------------------------------------------ */
510
511Int VG_(fork) ( void )
512{
513 SysRes res;
514 res = VG_(do_syscall0)(__NR_fork);
515 if (res.isError)
516 return -1;
sewardjd470bfc2006-10-17 02:16:44 +0000517 return res.res;
njnf39e9a32005-06-12 02:43:17 +0000518}
519
520/* ---------------------------------------------------------------------
521 Timing stuff
sewardj5f07b662002-04-23 16:52:51 +0000522 ------------------------------------------------------------------ */
523
sewardj5f07b662002-04-23 16:52:51 +0000524UInt VG_(read_millisecond_timer) ( void )
525{
sewardjd470bfc2006-10-17 02:16:44 +0000526 /* 'now' and 'base' are in microseconds */
fitzhardinge426f9e62004-01-25 03:44:18 +0000527 static ULong base = 0;
sewardja8d8e232005-06-07 20:04:56 +0000528 ULong now;
sewardj5f07b662002-04-23 16:52:51 +0000529
sewardjd470bfc2006-10-17 02:16:44 +0000530# if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
531 /* AIX requires a totally different implementation since
532 sys_gettimeofday doesn't exist. We use the POWER real-time
533 register facility. This will SIGILL on PowerPC 970 on AIX,
534 since PowerPC doesn't support these instructions. */
535 UWord nsec, sec1, sec2;
536 while (1) {
537 __asm__ __volatile__ ("\n"
538 "\tmfspr %0,4\n" /* 4==RTCU */
539 "\tmfspr %1,5\n" /* 5==RTCL */
540 "\tmfspr %2,4\n" /* 4==RTCU */
541 : "=b" (sec1), "=b" (nsec), "=b" (sec2)
542 );
543 if (sec1 == sec2) break;
544 }
545 vg_assert(nsec < 1000*1000*1000);
546 now = ((ULong)sec1) * 1000000ULL;
547 now += (ULong)(nsec / 1000);
548# else
549
bart1412d682008-05-14 09:50:08 +0000550 struct vki_timespec ts_now;
sewardjd470bfc2006-10-17 02:16:44 +0000551 SysRes res;
bart1412d682008-05-14 09:50:08 +0000552 res = VG_(do_syscall2)(__NR_clock_gettime, VKI_CLOCK_MONOTONIC,
553 (UWord)&ts_now);
554 if (res.isError == 0)
555 {
556 now = ts_now.tv_sec * 1000000ULL + ts_now.tv_nsec / 1000;
557 }
558 else
559 {
560 struct vki_timeval tv_now;
561 res = VG_(do_syscall2)(__NR_gettimeofday, (UWord)&tv_now, (UWord)NULL);
562 vg_assert(! res.isError);
563 now = tv_now.tv_sec * 1000000ULL + tv_now.tv_usec;
564 }
sewardjd470bfc2006-10-17 02:16:44 +0000565# endif
fitzhardinge66871692004-01-25 03:32:58 +0000566
567 if (base == 0)
568 base = now;
sewardj5f07b662002-04-23 16:52:51 +0000569
fitzhardinge66871692004-01-25 03:32:58 +0000570 return (now - base) / 1000;
sewardj5f07b662002-04-23 16:52:51 +0000571}
572
sewardj5f07b662002-04-23 16:52:51 +0000573/* ---------------------------------------------------------------------
njne9ba34a2008-10-13 04:19:15 +0000574 atfork()
sewardja8d8e232005-06-07 20:04:56 +0000575 ------------------------------------------------------------------ */
576
njne9ba34a2008-10-13 04:19:15 +0000577struct atfork {
578 vg_atfork_t pre;
579 vg_atfork_t parent;
580 vg_atfork_t child;
581};
sewardja8d8e232005-06-07 20:04:56 +0000582
njne9ba34a2008-10-13 04:19:15 +0000583#define VG_MAX_ATFORK 10
sewardja8d8e232005-06-07 20:04:56 +0000584
njne9ba34a2008-10-13 04:19:15 +0000585static struct atfork atforks[VG_MAX_ATFORK];
586static Int n_atfork = 0;
587
588void VG_(atfork)(vg_atfork_t pre, vg_atfork_t parent, vg_atfork_t child)
sewardja8d8e232005-06-07 20:04:56 +0000589{
njne9ba34a2008-10-13 04:19:15 +0000590 Int i;
sewardja8d8e232005-06-07 20:04:56 +0000591
njne9ba34a2008-10-13 04:19:15 +0000592 for (i = 0; i < n_atfork; i++) {
593 if (atforks[i].pre == pre &&
594 atforks[i].parent == parent &&
595 atforks[i].child == child)
596 return;
597 }
598
599 if (n_atfork >= VG_MAX_ATFORK)
600 VG_(core_panic)(
601 "Too many VG_(atfork) handlers requested: raise VG_MAX_ATFORK");
602
603 atforks[n_atfork].pre = pre;
604 atforks[n_atfork].parent = parent;
605 atforks[n_atfork].child = child;
606
607 n_atfork++;
608}
609
610void VG_(do_atfork_pre)(ThreadId tid)
611{
612 Int i;
613
614 for (i = 0; i < n_atfork; i++)
615 if (atforks[i].pre != NULL)
616 (*atforks[i].pre)(tid);
617}
618
619void VG_(do_atfork_parent)(ThreadId tid)
620{
621 Int i;
622
623 for (i = 0; i < n_atfork; i++)
624 if (atforks[i].parent != NULL)
625 (*atforks[i].parent)(tid);
sewardja8d8e232005-06-07 20:04:56 +0000626}
627
628void VG_(do_atfork_child)(ThreadId tid)
629{
njne9ba34a2008-10-13 04:19:15 +0000630 Int i;
631
632 for (i = 0; i < n_atfork; i++)
633 if (atforks[i].child != NULL)
634 (*atforks[i].child)(tid);
sewardja8d8e232005-06-07 20:04:56 +0000635}
636
sewardjde4a1d02002-03-22 01:27:54 +0000637/*--------------------------------------------------------------------*/
njnc6168192004-11-29 13:54:10 +0000638/*--- end ---*/
sewardjde4a1d02002-03-22 01:27:54 +0000639/*--------------------------------------------------------------------*/