2 /*--------------------------------------------------------------------*/
3 /*--- Client-space code for the core. vg_preloaded.c ---*/
4 /*--------------------------------------------------------------------*/
7 This file is part of Valgrind, a dynamic binary instrumentation
10 Copyright (C) 2000-2013 Julian Seward
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.
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.
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
28 The GNU General Public License is contained in the file COPYING.
32 /* ---------------------------------------------------------------------
33 ALL THE CODE IN THIS FILE RUNS ON THE SIMULATED CPU.
35 These functions are not called directly - they're the targets of code
36 redirection or load notifications (see pub_core_redir.h for info).
37 They're named weirdly so that the intercept code can find them when the
38 shared object is initially loaded.
40 Note that this filename has the "vg_" prefix because it can appear
41 in stack traces, and the "vg_" makes it a little clearer that it
42 originates from Valgrind.
43 ------------------------------------------------------------------ */
45 #include "pub_core_basics.h"
46 #include "pub_core_clreq.h"
47 #include "pub_core_debuginfo.h" // Needed for pub_core_redir.h
48 #include "pub_core_redir.h" // For VG_NOTIFY_ON_LOAD
50 #if defined(VGO_linux)
52 /* ---------------------------------------------------------------------
53 Hook for running __libc_freeres once the program exits.
54 ------------------------------------------------------------------ */
56 void VG_NOTIFY_ON_LOAD(freeres
)( void );
57 void VG_NOTIFY_ON_LOAD(freeres
)( void )
59 # if !defined(__UCLIBC__) \
60 && !defined(VGPV_arm_linux_android) \
61 && !defined(VGPV_x86_linux_android) \
62 && !defined(VGPV_mips32_linux_android) \
63 && !defined(VGPV_arm64_linux_android)
64 extern void __libc_freeres(void);
67 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__LIBC_FREERES_DONE
,
70 *(volatile int *)0 = 'x';
73 /* ---------------------------------------------------------------------
74 Wrapper for indirect functions which need to be redirected.
75 ------------------------------------------------------------------ */
77 void * VG_NOTIFY_ON_LOAD(ifunc_wrapper
) (void);
78 void * VG_NOTIFY_ON_LOAD(ifunc_wrapper
) (void)
84 /* Call the original indirect function and get it's result */
85 VALGRIND_GET_ORIG_FN(fn
);
86 CALL_FN_W_v(result
, fn
);
88 #if defined(VGP_ppc64be_linux)
89 /* ppc64be uses function descriptors, so get the actual function entry
90 address for the client request, but return the function descriptor
92 result points to the function descriptor, which starts with the
94 fnentry
= *(Addr
*)result
;
99 /* Ask the valgrind core running on the real CPU (as opposed to this
100 code which runs on the emulated CPU) to update the redirection that
101 led to this function. This client request eventually gives control to
102 the function VG_(redir_add_ifunc_target) in m_redir.c */
103 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__ADD_IFUNC_TARGET
,
104 fn
.nraddr
, fnentry
, 0, 0, 0);
105 return (void*)result
;
108 #elif defined(VGO_darwin)
110 #include "config.h" /* VERSION */
112 /* ---------------------------------------------------------------------
113 Darwin crash log hints
114 ------------------------------------------------------------------ */
116 /* This string will be inserted into crash logs, so crashes while
117 running under Valgrind can be distinguished from other crashes. */
118 __private_extern__
const char *__crashreporter_info__
= "Instrumented by Valgrind " VERSION
;
120 /* ---------------------------------------------------------------------
121 Darwin environment cleanup
122 ------------------------------------------------------------------ */
124 /* Scrubbing DYLD_INSERT_LIBRARIES from envp during exec is insufficient,
125 as there are other ways to launch a process with environment that
126 valgrind can't catch easily (i.e. launchd).
127 Instead, scrub DYLD_INSERT_LIBRARIES from the parent process once
128 dyld is done loading vg_preload.so.
131 #include <crt_externs.h>
133 // GrP fixme copied from m_libcproc
134 static void env_unsetenv ( HChar
**env
, const HChar
*varname
)
138 Int len
= strlen(varname
);
140 for (from
= to
= env
; from
&& *from
; from
++) {
141 if (!(strncmp(varname
, *from
, len
) == 0 && (*from
)[len
] == '=')) {
147 /* fix the 4th "char* apple" pointer (aka. executable path pointer) */
152 static void vg_cleanup_env(void) __attribute__((constructor
));
153 static void vg_cleanup_env(void)
155 HChar
**envp
= (HChar
**)*_NSGetEnviron();
156 env_unsetenv(envp
, "VALGRIND_LAUNCHER");
157 env_unsetenv(envp
, "DYLD_SHARED_REGION");
158 // GrP fixme should be more like mash_colon_env()
159 env_unsetenv(envp
, "DYLD_INSERT_LIBRARIES");
162 /* ---------------------------------------------------------------------
163 Darwin arc4random (rdar://6166275)
164 ------------------------------------------------------------------ */
169 int VG_REPLACE_FUNCTION_ZU(libSystemZdZaZddylib
, arc4random
)(void);
170 int VG_REPLACE_FUNCTION_ZU(libSystemZdZaZddylib
, arc4random
)(void)
175 if (rnd
< 0) rnd
= open("/dev/random", O_RDONLY
);
177 read(rnd
, &result
, sizeof(result
));
181 void VG_REPLACE_FUNCTION_ZU(libSystemZdZaZddylib
, arc4random_stir
)(void);
182 void VG_REPLACE_FUNCTION_ZU(libSystemZdZaZddylib
, arc4random_stir
)(void)
187 void VG_REPLACE_FUNCTION_ZU(libSystemZdZaZddylib
, arc4random_addrandom
)(unsigned char *dat
, int datlen
);
188 void VG_REPLACE_FUNCTION_ZU(libSystemZdZaZddylib
, arc4random_addrandom
)(unsigned char *dat
, int datlen
)
191 // GrP fixme ought to check [dat..dat+datlen) is defined
192 // but don't care if it's initialized
195 #elif defined(VGO_solaris)
197 /* Declare the errno and environ symbols weakly in case the client is not
198 linked against libc. In such a case it also cannot run replacement
199 functions for set_error() and spawnveg() where these two variables are
200 needed so this is ok. */
201 __attribute__((weak
)) extern int errno
;
202 __attribute__((weak
)) extern char **environ
;
207 #include <sys/syscall.h>
208 #include <sys/signal.h>
211 /* Replace function block_all_signals() from libc. When the client program is
212 not running under valgrind, the function blocks all signals by setting
213 sc_sigblock flag in the schedctl control block. When run under Valgrind
214 this would bypass Valgrind's syscall and signal machinery.
215 Valgrind's signal machinery needs to retain control over which signals are
216 blocked and which not (see m_signals.c and m_scheduler/scheduler.c for more
217 information - typically synchronous signals should not be blocked).
218 Therefore this function replacement emulates lwp_sigmask syscall.
220 void VG_REPLACE_FUNCTION_ZU(VG_Z_LIBC_SONAME
, block_all_signals
)(/*ulwp_t*/ void *self
);
221 void VG_REPLACE_FUNCTION_ZU(VG_Z_LIBC_SONAME
, block_all_signals
)(/*ulwp_t*/ void *self
)
223 syscall(SYS_lwp_sigmask
, SIG_SETMASK
, ~0U, ~0U, ~0U, ~0U);
226 /* Replace functions get_error() and set_error() in libc. These functions are
227 internal to the library and are used to work with an error value returned
228 by posix_spawn() (when it is implemented using vfork()). A child calls
229 set_error() to set an error code and the parent then calls get_error() to
230 read it. Accessor functions are used so these trivial store+load operations
231 are not changed by the compiler in any way.
233 Since Valgrind translates vfork() to a normal fork(), calling set_error()
234 by the child would have no effect on the error value in the parent so
235 something must be done to fix this problem.
237 A pipe is created between a child and its parent in the forksys pre-wrapper
238 when a vfork() is encountered. The child's end of the pipe is closed when
239 the child exits or execs (because close-on-exec is set on the file
240 descriptor). Valgrind (the parent) waits on the child's end of the pipe to
241 be closed which preserves the vfork() behaviour that the parent process is
242 suspended while the child is using its resources.
244 The pipe is then used to send an eventual error code set by the child in
245 posix_spawn() to the parent. If there is any error Valgrind returns it as
246 an error from the vfork() syscall. This means the syscall can return errors
247 that it would normally never return but this is not a problem in practice
248 because any error is directly propagated as a return code from
251 Address of vg_vfork_fildes is found by Valgrind when debug information for
252 vgpreload_core.so is being processed. A value of this variable is set in
253 the forksys pre-wrapper before a fork() call is made and set back to -1
254 before returning from the wrapper by the parent.
256 Newer Solaris versions introduce the spawn syscall and posix_spawn() is
257 implemented using it. The redirect is not needed for these versions.
259 int vg_vfork_fildes
= -1;
261 int VG_REPLACE_FUNCTION_ZU(VG_Z_LIBC_SONAME
, get_error
)(int *errp
);
262 int VG_REPLACE_FUNCTION_ZU(VG_Z_LIBC_SONAME
, get_error
)(int *errp
)
264 /* Always return 0 when the parent tries to call get_error(). Any error
265 from the child is returned directly as an error from the vfork child.
266 Value pointed by errp is initialized only by the child so not
267 redirecting this function would mean that the parent gets an
268 uninitialized/garbage value when it calls this function. */
272 int VG_REPLACE_FUNCTION_ZU(VG_Z_LIBC_SONAME
, set_error
)(int *errp
, int err
);
273 int VG_REPLACE_FUNCTION_ZU(VG_Z_LIBC_SONAME
, set_error
)(int *errp
, int err
)
277 /* Libc should always call set_error() only after doing a vfork() syscall
278 in posix_spawn(). The forksys pre-wrapper saves a descriptor of the
279 child's end of the pipe in vg_vfork_fildes so it is an error if it is
280 not a valid file descriptor at this point. */
281 assert(vg_vfork_fildes
>= 0);
282 /* Current protocol between this function and the forksys pre-wrapper
283 allows to send only errors in range [0, 255] (one byte values). */
284 assert(err
>= 0 && err
<= 0xff);
287 unsigned char w
= (unsigned char)(err
& 0xff);
290 res
= write(vg_vfork_fildes
, &w
, 1);
291 assert(res
== 1 || (errno
== EINTR
|| errno
== ERESTART
));
298 /* Replace spawnveg() in libast.so.1. This function is used by ksh to spawn
299 new processes. The library has a build time option to select between
300 several variants of this function based on behaviour of vfork() and
301 posix_spawn() on the system for which the library is being compiled.
302 Unfortunately, Solaris and illumos use the real vfork() variant which does
303 not work correctly with the vfork() -> fork() translation done by Valgrind
304 (see the forksys pre-wrapper for details). Therefore the function is
305 replaced here with an implementation that uses posix_spawn(). This
306 replacement can be removed when a configuration of libast in Solaris and
307 illumos is changed to use the posix_spawn() implementation.
309 pid_t
VG_REPLACE_FUNCTION_ZU(libastZdsoZd1
, spawnveg
)(const char *command
,
313 pid_t
VG_REPLACE_FUNCTION_ZU(libastZdsoZd1
, spawnveg
)(const char *command
,
320 posix_spawnattr_t attr
;
321 int attr_init_done
= 0;
323 err
= posix_spawnattr_init(&attr
);
328 err
= posix_spawnattr_init(&attr
);
335 err
= posix_spawnattr_setpgroup(&attr
, pgid
);
338 err
= posix_spawnattr_setflags(&attr
, POSIX_SPAWN_SETPGROUP
);
343 err
= posix_spawn(&pid
, command
, NULL
, &attr
, argv
, envp
? envp
: environ
);
347 posix_spawnattr_destroy(&attr
);
359 /*--------------------------------------------------------------------*/
361 /*--------------------------------------------------------------------*/