blob: d910bc78285612ac7a38e2bdf884649cbbc3f117 [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
njn53612422005-03-12 16:22:54 +000010 Copyright (C) 2000-2005 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"
njn97405b22005-06-02 03:39:33 +000032#include "pub_core_libcbase.h"
njn132bfcc2005-06-04 19:16:06 +000033#include "pub_core_libcassert.h"
njn36a20fa2005-06-03 03:08:39 +000034#include "pub_core_libcprint.h"
njnf39e9a32005-06-12 02:43:17 +000035#include "pub_core_libcproc.h"
njnaf1d7df2005-06-11 01:31:52 +000036#include "pub_core_mallocfree.h"
njn9abd6082005-06-17 21:31:45 +000037#include "pub_core_syscall.h"
njn3c660b62005-05-13 22:18:47 +000038#include "vki_unistd.h"
sewardj1cf558c2005-04-25 01:36:56 +000039
njnf39e9a32005-06-12 02:43:17 +000040/* ---------------------------------------------------------------------
41 Command line and environment stuff
42 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +000043
njnf39e9a32005-06-12 02:43:17 +000044/* As deduced from sp_at_startup, the client's argc, argv[] and
45 envp[] as extracted from the client's stack at startup-time. */
46Int VG_(client_argc);
47Char** VG_(client_argv);
48Char** VG_(client_envp);
49
njn75b65aa2005-06-19 19:25:44 +000050/* client executable file descriptor */
njn24cf3e02005-06-19 19:38:03 +000051Int VG_(clexecfd) = -1;
njn75b65aa2005-06-19 19:25:44 +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;
61 n = VG_(strlen)(varname);
62 for (i = 0; VG_(client_envp)[i] != NULL; i++) {
63 Char* s = VG_(client_envp)[i];
64 if (VG_(strncmp)(varname, s, n) == 0 && s[n] == '=') {
65 return & s[n+1];
thughes8ef6d962004-10-16 10:46:01 +000066 }
67 }
njnf39e9a32005-06-12 02:43:17 +000068 return NULL;
nethercoteff9721d2004-01-26 17:10:01 +000069}
70
fitzhardinge98abfc72003-12-16 02:05:15 +000071void VG_(env_unsetenv) ( Char **env, const Char *varname )
72{
73 Char **from;
74 Char **to = NULL;
75 Int len = VG_(strlen)(varname);
76
77 for(from = to = env; from && *from; from++) {
78 if (!(VG_(strncmp)(varname, *from, len) == 0 && (*from)[len] == '=')) {
79 *to = *from;
80 to++;
81 }
82 }
83 *to = *from;
84}
85
86/* set the environment; returns the old env if a new one was allocated */
87Char **VG_(env_setenv) ( Char ***envp, const Char* varname, const Char *val )
88{
89 Char **env = (*envp);
90 Char **cpp;
91 Int len = VG_(strlen)(varname);
92 Char *valstr = VG_(arena_malloc)(VG_AR_CORE, len + VG_(strlen)(val) + 2);
93 Char **oldenv = NULL;
94
95 VG_(sprintf)(valstr, "%s=%s", varname, val);
96
97 for(cpp = env; cpp && *cpp; cpp++) {
98 if (VG_(strncmp)(varname, *cpp, len) == 0 && (*cpp)[len] == '=') {
99 *cpp = valstr;
100 return oldenv;
101 }
102 }
103
104 if (env == NULL) {
105 env = VG_(arena_malloc)(VG_AR_CORE, sizeof(Char **) * 2);
106 env[0] = valstr;
107 env[1] = NULL;
108
109 *envp = env;
110
111 } else {
112 Int envlen = (cpp-env) + 2;
113 Char **newenv = VG_(arena_malloc)(VG_AR_CORE, envlen * sizeof(Char **));
114
115 for(cpp = newenv; *env; )
116 *cpp++ = *env++;
117 *cpp++ = valstr;
118 *cpp++ = NULL;
119
120 oldenv = *envp;
121
122 *envp = newenv;
123 }
124
125 return oldenv;
126}
127
nethercote60a96c52004-08-03 13:08:31 +0000128/* Walk through a colon-separated environment variable, and remove the
129 entries which match remove_pattern. It slides everything down over
130 the removed entries, and pads the remaining space with '\0'. It
131 modifies the entries in place (in the client address space), but it
132 shouldn't matter too much, since we only do this just before an
133 execve().
134
135 This is also careful to mop up any excess ':'s, since empty strings
136 delimited by ':' are considered to be '.' in a path.
137*/
138static void mash_colon_env(Char *varp, const Char *remove_pattern)
139{
140 Char *const start = varp;
141 Char *entry_start = varp;
142 Char *output = varp;
143
144 if (varp == NULL)
145 return;
146
147 while(*varp) {
148 if (*varp == ':') {
149 Char prev;
150 Bool match;
151
152 /* This is a bit subtle: we want to match against the entry
153 we just copied, because it may have overlapped with
154 itself, junking the original. */
155
156 prev = *output;
157 *output = '\0';
158
159 match = VG_(string_match)(remove_pattern, entry_start);
160
161 *output = prev;
162
163 if (match) {
164 output = entry_start;
165 varp++; /* skip ':' after removed entry */
166 } else
167 entry_start = output+1; /* entry starts after ':' */
168 }
169
170 *output++ = *varp++;
171 }
172
173 /* match against the last entry */
174 if (VG_(string_match)(remove_pattern, entry_start)) {
175 output = entry_start;
176 if (output > start) {
177 /* remove trailing ':' */
178 output--;
179 vg_assert(*output == ':');
180 }
181 }
182
183 /* pad out the left-overs with '\0' */
184 while(output < varp)
185 *output++ = '\0';
186}
187
188
189// Removes all the Valgrind-added stuff from the passed environment. Used
190// when starting child processes, so they don't see that added stuff.
191void VG_(env_remove_valgrind_env_stuff)(Char** envp)
192{
193 Int i;
194 Char* ld_preload_str = NULL;
195 Char* ld_library_path_str = NULL;
196 Char* buf;
197
198 // Find LD_* variables
199 for (i = 0; envp[i] != NULL; i++) {
200 if (VG_(strncmp)(envp[i], "LD_PRELOAD=", 11) == 0)
201 ld_preload_str = &envp[i][11];
202 if (VG_(strncmp)(envp[i], "LD_LIBRARY_PATH=", 16) == 0)
203 ld_library_path_str = &envp[i][16];
204 }
205
206 buf = VG_(arena_malloc)(VG_AR_CORE, VG_(strlen)(VG_(libdir)) + 20);
207
208 // Remove Valgrind-specific entries from LD_*.
njn16eeb4e2005-06-16 03:56:58 +0000209 VG_(sprintf)(buf, "%s*/vg_preload_core.so", VG_(libdir));
nethercote60a96c52004-08-03 13:08:31 +0000210 mash_colon_env(ld_preload_str, buf);
211 VG_(sprintf)(buf, "%s*/vgpreload_*.so", VG_(libdir));
212 mash_colon_env(ld_preload_str, buf);
213 VG_(sprintf)(buf, "%s*", VG_(libdir));
214 mash_colon_env(ld_library_path_str, buf);
215
216 // Remove VALGRIND_CLO variable.
217 VG_(env_unsetenv)(envp, VALGRINDCLO);
218
219 // XXX if variable becomes empty, remove it completely?
220
221 VG_(arena_free)(VG_AR_CORE, buf);
222}
223
njnf39e9a32005-06-12 02:43:17 +0000224/* ---------------------------------------------------------------------
225 Various important syscall wrappers
226 ------------------------------------------------------------------ */
227
228Int VG_(waitpid)(Int pid, Int *status, Int options)
229{
230 SysRes res = VG_(do_syscall4)(__NR_wait4, pid, (UWord)status, options, 0);
231 return res.isError ? -1 : res.val;
232}
233
njnf39e9a32005-06-12 02:43:17 +0000234Int VG_(poll)( struct vki_pollfd *ufds, UInt nfds, Int timeout)
235{
236 SysRes res = VG_(do_syscall3)(__NR_poll, (UWord)ufds, nfds, timeout);
237 /* ASSUMES SYSCALL ALWAYS SUCCEEDS */
238 return res.val;
239}
240
241/* clone the environment */
242static Char **env_clone ( Char **oldenv )
243{
244 Char **oldenvp;
245 Char **newenvp;
246 Char **newenv;
247 Int envlen;
248
249 for (oldenvp = oldenv; oldenvp && *oldenvp; oldenvp++);
250
251 envlen = oldenvp - oldenv + 1;
252
253 newenv = VG_(arena_malloc)(VG_AR_CORE, envlen * sizeof(Char **));
254
255 oldenvp = oldenv;
256 newenvp = newenv;
257
258 while (oldenvp && *oldenvp) {
259 *newenvp++ = *oldenvp++;
260 }
261
262 *newenvp = *oldenvp;
263
264 return newenv;
265}
266
sewardje6a25242002-04-21 22:03:07 +0000267/* Return -1 if error, else 0. NOTE does not indicate return code of
268 child! */
269Int VG_(system) ( Char* cmd )
270{
sewardja8d8e232005-06-07 20:04:56 +0000271 Int pid;
272 SysRes res;
sewardje6a25242002-04-21 22:03:07 +0000273 if (cmd == NULL)
274 return 1;
sewardja8d8e232005-06-07 20:04:56 +0000275 res = VG_(do_syscall0)(__NR_fork);
276 if (res.isError)
sewardje6a25242002-04-21 22:03:07 +0000277 return -1;
sewardja8d8e232005-06-07 20:04:56 +0000278 pid = res.val;
sewardje6a25242002-04-21 22:03:07 +0000279 if (pid == 0) {
280 /* child */
nethercoteff9721d2004-01-26 17:10:01 +0000281 static Char** envp = NULL;
sewardje6a25242002-04-21 22:03:07 +0000282 Char* argv[4];
nethercoteff9721d2004-01-26 17:10:01 +0000283
fitzhardingeb50068f2004-02-24 23:42:55 +0000284 /* restore the DATA rlimit for the child */
285 VG_(setrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
286
nethercote60a96c52004-08-03 13:08:31 +0000287 envp = env_clone(VG_(client_envp));
288 VG_(env_remove_valgrind_env_stuff)( envp );
nethercoteff9721d2004-01-26 17:10:01 +0000289
sewardje6a25242002-04-21 22:03:07 +0000290 argv[0] = "/bin/sh";
291 argv[1] = "-c";
292 argv[2] = cmd;
293 argv[3] = 0;
nethercoteff9721d2004-01-26 17:10:01 +0000294
njnca6fef02004-11-29 16:49:18 +0000295 (void)VG_(do_syscall3)(__NR_execve,
296 (UWord)"/bin/sh", (UWord)argv, (UWord)envp);
nethercoteff9721d2004-01-26 17:10:01 +0000297
sewardje6a25242002-04-21 22:03:07 +0000298 /* If we're still alive here, execve failed. */
fitzhardingeabab8392004-03-02 21:38:51 +0000299 VG_(exit)(1);
sewardje6a25242002-04-21 22:03:07 +0000300 } else {
301 /* parent */
sewardja8d8e232005-06-07 20:04:56 +0000302 Int zzz = VG_(waitpid)(pid, NULL, 0);
303 return zzz == -1 ? -1 : 0;
sewardje6a25242002-04-21 22:03:07 +0000304 }
305}
306
njnf39e9a32005-06-12 02:43:17 +0000307/* ---------------------------------------------------------------------
308 Resource limits
309 ------------------------------------------------------------------ */
310
311struct vki_rlimit VG_(client_rlimit_data);
312struct vki_rlimit VG_(client_rlimit_stack);
313
314/* Support for getrlimit. */
315Int VG_(getrlimit) (Int resource, struct vki_rlimit *rlim)
316{
317 SysRes res = VG_(mk_SysRes_Error)(VKI_ENOSYS);
318 /* res = getrlimit( resource, rlim ); */
319# ifdef __NR_ugetrlimit
320 res = VG_(do_syscall2)(__NR_ugetrlimit, resource, (UWord)rlim);
321# endif
322 if (res.isError && res.val == VKI_ENOSYS)
323 res = VG_(do_syscall2)(__NR_getrlimit, resource, (UWord)rlim);
324 return res.isError ? -1 : res.val;
325}
326
327
328/* Support for setrlimit. */
329Int VG_(setrlimit) (Int resource, const struct vki_rlimit *rlim)
330{
331 SysRes res;
332 /* res = setrlimit( resource, rlim ); */
333 res = VG_(do_syscall2)(__NR_setrlimit, resource, (UWord)rlim);
334 return res.isError ? -1 : res.val;
335}
sewardje6a25242002-04-21 22:03:07 +0000336
sewardjde4a1d02002-03-22 01:27:54 +0000337/* ---------------------------------------------------------------------
njnf39e9a32005-06-12 02:43:17 +0000338 pids, etc
339 ------------------------------------------------------------------ */
340
341Int VG_(gettid)(void)
342{
343 SysRes res = VG_(do_syscall0)(__NR_gettid);
344
345 if (res.isError && res.val == VKI_ENOSYS) {
346 Char pid[16];
347 /*
348 * The gettid system call does not exist. The obvious assumption
349 * to make at this point would be that we are running on an older
350 * system where the getpid system call actually returns the ID of
351 * the current thread.
352 *
353 * Unfortunately it seems that there are some systems with a kernel
354 * where getpid has been changed to return the ID of the thread group
355 * leader but where the gettid system call has not yet been added.
356 *
357 * So instead of calling getpid here we use readlink to see where
358 * the /proc/self link is pointing...
359 */
360
361 res = VG_(do_syscall3)(__NR_readlink, (UWord)"/proc/self",
362 (UWord)pid, sizeof(pid));
363 if (!res.isError && res.val > 0) {
364 pid[res.val] = '\0';
365 res.val = VG_(atoll)(pid);
366 }
367 }
368
369 return res.val;
370}
371
372/* You'd be amazed how many places need to know the current pid. */
373Int VG_(getpid) ( void )
374{
375 /* ASSUMES SYSCALL ALWAYS SUCCEEDS */
376 return VG_(do_syscall0)(__NR_getpid) . val;
377}
378
379Int VG_(getpgrp) ( void )
380{
381 /* ASSUMES SYSCALL ALWAYS SUCCEEDS */
382 return VG_(do_syscall0)(__NR_getpgrp) . val;
383}
384
385Int VG_(getppid) ( void )
386{
387 /* ASSUMES SYSCALL ALWAYS SUCCEEDS */
388 return VG_(do_syscall0)(__NR_getppid) . val;
389}
390
391Int VG_(setpgid) ( Int pid, Int pgrp )
392{
393 /* ASSUMES SYSCALL ALWAYS SUCCEEDS */
394 return VG_(do_syscall2)(__NR_setpgid, pid, pgrp) . val;
395}
396
397/* ---------------------------------------------------------------------
398 Timing stuff
sewardj5f07b662002-04-23 16:52:51 +0000399 ------------------------------------------------------------------ */
400
sewardj5f07b662002-04-23 16:52:51 +0000401UInt VG_(read_millisecond_timer) ( void )
402{
fitzhardinge426f9e62004-01-25 03:44:18 +0000403 static ULong base = 0;
fitzhardinge66871692004-01-25 03:32:58 +0000404 struct vki_timeval tv_now;
sewardja8d8e232005-06-07 20:04:56 +0000405 ULong now;
406 SysRes res;
sewardj5f07b662002-04-23 16:52:51 +0000407
njnca6fef02004-11-29 16:49:18 +0000408 res = VG_(do_syscall2)(__NR_gettimeofday, (UWord)&tv_now, (UWord)NULL);
sewardj5f07b662002-04-23 16:52:51 +0000409
fitzhardinge66871692004-01-25 03:32:58 +0000410 now = tv_now.tv_sec * 1000000ULL + tv_now.tv_usec;
411
412 if (base == 0)
413 base = now;
sewardj5f07b662002-04-23 16:52:51 +0000414
fitzhardinge66871692004-01-25 03:32:58 +0000415 return (now - base) / 1000;
sewardj5f07b662002-04-23 16:52:51 +0000416}
417
418
sewardjb5f6f512005-03-10 23:59:00 +0000419void VG_(nanosleep)(struct vki_timespec *ts)
420{
sewardja8d8e232005-06-07 20:04:56 +0000421 (void)VG_(do_syscall2)(__NR_nanosleep, (UWord)ts, (UWord)NULL);
sewardjb5f6f512005-03-10 23:59:00 +0000422}
423
sewardj5f07b662002-04-23 16:52:51 +0000424/* ---------------------------------------------------------------------
njn310ed282005-06-26 15:11:37 +0000425 A trivial atfork() facility for Valgrind's internal use
sewardja8d8e232005-06-07 20:04:56 +0000426 ------------------------------------------------------------------ */
427
njn310ed282005-06-26 15:11:37 +0000428// Trivial because it only supports a single post-fork child action, which
429// is all we need.
sewardja8d8e232005-06-07 20:04:56 +0000430
njn310ed282005-06-26 15:11:37 +0000431static vg_atfork_t atfork_child = NULL;
sewardja8d8e232005-06-07 20:04:56 +0000432
njn310ed282005-06-26 15:11:37 +0000433void VG_(atfork_child)(vg_atfork_t child)
sewardja8d8e232005-06-07 20:04:56 +0000434{
njn310ed282005-06-26 15:11:37 +0000435 if (NULL != atfork_child)
436 VG_(core_panic)("More than one atfork_child handler requested");
sewardja8d8e232005-06-07 20:04:56 +0000437
njn310ed282005-06-26 15:11:37 +0000438 atfork_child = child;
sewardja8d8e232005-06-07 20:04:56 +0000439}
440
441void VG_(do_atfork_child)(ThreadId tid)
442{
njn310ed282005-06-26 15:11:37 +0000443 if (NULL != atfork_child)
444 (*atfork_child)(tid);
sewardja8d8e232005-06-07 20:04:56 +0000445}
446
sewardjde4a1d02002-03-22 01:27:54 +0000447/*--------------------------------------------------------------------*/
njnc6168192004-11-29 13:54:10 +0000448/*--- end ---*/
sewardjde4a1d02002-03-22 01:27:54 +0000449/*--------------------------------------------------------------------*/