Update following recent bug-fix commits.
[valgrind.git] / coregrind / vg_preloaded.c
blob3ea3761f97dbcef1c76ff3f57a14f9b3355f171c
2 /*--------------------------------------------------------------------*/
3 /*--- Client-space code for the core. vg_preloaded.c ---*/
4 /*--------------------------------------------------------------------*/
6 /*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
10 Copyright (C) 2000-2017 Julian Seward
11 jseward@acm.org
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, see <http://www.gnu.org/licenses/>.
26 The GNU General Public License is contained in the file COPYING.
30 /* ---------------------------------------------------------------------
31 ALL THE CODE IN THIS FILE RUNS ON THE SIMULATED CPU.
33 These functions are not called directly - they're the targets of code
34 redirection or load notifications (see pub_core_redir.h for info).
35 They're named weirdly so that the intercept code can find them when the
36 shared object is initially loaded.
38 Note that this filename has the "vg_" prefix because it can appear
39 in stack traces, and the "vg_" makes it a little clearer that it
40 originates from Valgrind.
41 ------------------------------------------------------------------ */
43 #include "pub_core_basics.h"
44 #include "pub_core_clreq.h"
45 #include "pub_core_debuginfo.h" // Needed for pub_core_redir.h
46 #include "pub_core_redir.h" // For VG_NOTIFY_ON_LOAD
48 #if defined(VGO_linux) || defined(VGO_solaris)
50 /* ---------------------------------------------------------------------
51 Hook for running __gnu_cxx::__freeres() and __libc_freeres() once
52 the program exits.
53 ------------------------------------------------------------------ */
55 void VG_NOTIFY_ON_LOAD(freeres)(Vg_FreeresToRun to_run);
56 void VG_NOTIFY_ON_LOAD(freeres)(Vg_FreeresToRun to_run)
58 # if !defined(__UCLIBC__) && !defined(MUSL_LIBC) \
59 && !defined(VGPV_arm_linux_android) \
60 && !defined(VGPV_x86_linux_android) \
61 && !defined(VGPV_mips32_linux_android) \
62 && !defined(VGPV_arm64_linux_android)
64 /* g++ mangled __gnu_cxx::__freeres yields -> _ZN9__gnu_cxx9__freeresEv */
65 extern void _ZN9__gnu_cxx9__freeresEv(void) __attribute__((weak));
66 if (((to_run & VG_RUN__GNU_CXX__FREERES) != 0) &&
67 (_ZN9__gnu_cxx9__freeresEv != NULL)) {
68 _ZN9__gnu_cxx9__freeresEv();
71 # if defined(VGO_linux)
72 /* __libc_freeres() not yet available on Solaris. */
73 extern void __libc_freeres(void);
74 if ((to_run & VG_RUN__LIBC_FREERES) != 0) {
75 __libc_freeres();
77 # endif
78 # endif
80 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__FREERES_DONE, 0, 0, 0, 0, 0);
81 /*NOTREACHED*/
82 *(volatile int *)0 = 'x';
85 #endif // VGO_linux || VGO_solaris
87 #if defined(VGO_linux)
89 /* ---------------------------------------------------------------------
90 Wrapper for indirect functions which need to be redirected.
91 ------------------------------------------------------------------ */
93 void * VG_NOTIFY_ON_LOAD(ifunc_wrapper) (void);
94 void * VG_NOTIFY_ON_LOAD(ifunc_wrapper) (void)
96 OrigFn fn;
97 Addr result = 0;
98 Addr fnentry;
100 /* Call the original indirect function and get it's result */
101 VALGRIND_GET_ORIG_FN(fn);
102 CALL_FN_W_v(result, fn);
104 #if defined(VGP_ppc64be_linux)
105 /* ppc64be uses function descriptors, so get the actual function entry
106 address for the client request, but return the function descriptor
107 from this function.
108 result points to the function descriptor, which starts with the
109 function entry. */
110 fnentry = *(Addr*)result;
111 #else
112 fnentry = result;
113 #endif
115 /* Ask the valgrind core running on the real CPU (as opposed to this
116 code which runs on the emulated CPU) to update the redirection that
117 led to this function. This client request eventually gives control to
118 the function VG_(redir_add_ifunc_target) in m_redir.c */
119 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__ADD_IFUNC_TARGET,
120 fn.nraddr, fnentry, 0, 0, 0);
121 return (void*)result;
124 #elif defined(VGO_darwin)
126 #include "config.h" /* VERSION */
128 /* ---------------------------------------------------------------------
129 Darwin crash log hints
130 ------------------------------------------------------------------ */
132 /* This string will be inserted into crash logs, so crashes while
133 running under Valgrind can be distinguished from other crashes. */
134 __private_extern__ const char *__crashreporter_info__ = "Instrumented by Valgrind " VERSION;
136 /* ---------------------------------------------------------------------
137 Darwin environment cleanup
138 ------------------------------------------------------------------ */
140 /* Scrubbing DYLD_INSERT_LIBRARIES from envp during exec is insufficient,
141 as there are other ways to launch a process with environment that
142 valgrind can't catch easily (i.e. launchd).
143 Instead, scrub DYLD_INSERT_LIBRARIES from the parent process once
144 dyld is done loading vg_preload.so.
146 #include <string.h>
147 #include <crt_externs.h>
149 // GrP fixme copied from m_libcproc
150 static void env_unsetenv ( HChar **env, const HChar *varname )
152 HChar **from;
153 HChar **to = NULL;
154 Int len = strlen(varname);
156 for (from = to = env; from && *from; from++) {
157 if (!(strncmp(varname, *from, len) == 0 && (*from)[len] == '=')) {
158 *to = *from;
159 to++;
162 *(to++) = *(from++);
163 /* fix the 4th "char* apple" pointer (aka. executable path pointer) */
164 *(to++) = *(from++);
165 *to = NULL;
168 static void vg_cleanup_env(void) __attribute__((constructor));
169 static void vg_cleanup_env(void)
171 HChar **envp = (HChar**)*_NSGetEnviron();
172 env_unsetenv(envp, "VALGRIND_LAUNCHER");
173 env_unsetenv(envp, "DYLD_SHARED_REGION");
174 // GrP fixme should be more like mash_colon_env()
175 env_unsetenv(envp, "DYLD_INSERT_LIBRARIES");
178 /* ---------------------------------------------------------------------
179 Darwin arc4random (rdar://6166275)
180 ------------------------------------------------------------------ */
182 #include <fcntl.h>
183 #include <unistd.h>
185 int VG_REPLACE_FUNCTION_ZU(libSystemZdZaZddylib, arc4random)(void);
186 int VG_REPLACE_FUNCTION_ZU(libSystemZdZaZddylib, arc4random)(void)
188 static int rnd = -1;
189 int result;
191 if (rnd < 0) rnd = open("/dev/random", O_RDONLY);
193 read(rnd, &result, sizeof(result));
194 return result;
197 void VG_REPLACE_FUNCTION_ZU(libSystemZdZaZddylib, arc4random_stir)(void);
198 void VG_REPLACE_FUNCTION_ZU(libSystemZdZaZddylib, arc4random_stir)(void)
200 // do nothing
203 void VG_REPLACE_FUNCTION_ZU(libSystemZdZaZddylib, arc4random_addrandom)(unsigned char *dat, int datlen);
204 void VG_REPLACE_FUNCTION_ZU(libSystemZdZaZddylib, arc4random_addrandom)(unsigned char *dat, int datlen)
206 // do nothing
207 // GrP fixme ought to check [dat..dat+datlen) is defined
208 // but don't care if it's initialized
211 #elif defined(VGO_solaris)
213 /* Declare the errno and environ symbols weakly in case the client is not
214 linked against libc. In such a case it also cannot run replacement
215 functions for set_error() and spawnveg() where these two variables are
216 needed so this is ok. */
217 __attribute__((weak)) extern int errno;
218 __attribute__((weak)) extern char **environ;
220 #include <assert.h>
221 #include <errno.h>
222 #include <spawn.h>
223 #include <sys/syscall.h>
224 #include <sys/signal.h>
225 #include <unistd.h>
227 /* Replace function block_all_signals() from libc. When the client program is
228 not running under valgrind, the function blocks all signals by setting
229 sc_sigblock flag in the schedctl control block. When run under Valgrind
230 this would bypass Valgrind's syscall and signal machinery.
231 Valgrind's signal machinery needs to retain control over which signals are
232 blocked and which not (see m_signals.c and m_scheduler/scheduler.c for more
233 information - typically synchronous signals should not be blocked).
234 Therefore this function replacement emulates lwp_sigmask syscall.
236 void VG_REPLACE_FUNCTION_ZU(VG_Z_LIBC_SONAME, block_all_signals)(/*ulwp_t*/ void *self);
237 void VG_REPLACE_FUNCTION_ZU(VG_Z_LIBC_SONAME, block_all_signals)(/*ulwp_t*/ void *self)
239 syscall(SYS_lwp_sigmask, SIG_SETMASK, ~0U, ~0U, ~0U, ~0U);
242 /* Replace functions get_error() and set_error() in libc. These functions are
243 internal to the library and are used to work with an error value returned
244 by posix_spawn() (when it is implemented using vfork()). A child calls
245 set_error() to set an error code and the parent then calls get_error() to
246 read it. Accessor functions are used so these trivial store+load operations
247 are not changed by the compiler in any way.
249 Since Valgrind translates vfork() to a normal fork(), calling set_error()
250 by the child would have no effect on the error value in the parent so
251 something must be done to fix this problem.
253 A pipe is created between a child and its parent in the forksys pre-wrapper
254 when a vfork() is encountered. The child's end of the pipe is closed when
255 the child exits or execs (because close-on-exec is set on the file
256 descriptor). Valgrind (the parent) waits on the child's end of the pipe to
257 be closed which preserves the vfork() behaviour that the parent process is
258 suspended while the child is using its resources.
260 The pipe is then used to send an eventual error code set by the child in
261 posix_spawn() to the parent. If there is any error Valgrind returns it as
262 an error from the vfork() syscall. This means the syscall can return errors
263 that it would normally never return but this is not a problem in practice
264 because any error is directly propagated as a return code from
265 posix_spawn().
267 Address of vg_vfork_fildes is found by Valgrind when debug information for
268 vgpreload_core.so is being processed. A value of this variable is set in
269 the forksys pre-wrapper before a fork() call is made and set back to -1
270 before returning from the wrapper by the parent.
272 Newer Solaris versions introduce the spawn syscall and posix_spawn() is
273 implemented using it. The redirect is not needed for these versions.
275 int vg_vfork_fildes = -1;
277 int VG_REPLACE_FUNCTION_ZU(VG_Z_LIBC_SONAME, get_error)(int *errp);
278 int VG_REPLACE_FUNCTION_ZU(VG_Z_LIBC_SONAME, get_error)(int *errp)
280 /* Always return 0 when the parent tries to call get_error(). Any error
281 from the child is returned directly as an error from the vfork child.
282 Value pointed by errp is initialized only by the child so not
283 redirecting this function would mean that the parent gets an
284 uninitialized/garbage value when it calls this function. */
285 return 0;
288 int VG_REPLACE_FUNCTION_ZU(VG_Z_LIBC_SONAME, set_error)(int *errp, int err);
289 int VG_REPLACE_FUNCTION_ZU(VG_Z_LIBC_SONAME, set_error)(int *errp, int err)
291 *errp = err;
293 /* Libc should always call set_error() only after doing a vfork() syscall
294 in posix_spawn(). The forksys pre-wrapper saves a descriptor of the
295 child's end of the pipe in vg_vfork_fildes so it is an error if it is
296 not a valid file descriptor at this point. */
297 assert(vg_vfork_fildes >= 0);
298 /* Current protocol between this function and the forksys pre-wrapper
299 allows to send only errors in range [0, 255] (one byte values). */
300 assert(err >= 0 && err <= 0xff);
302 if (err != 0) {
303 unsigned char w = (unsigned char)(err & 0xff);
304 ssize_t res;
305 do {
306 res = write(vg_vfork_fildes, &w, 1);
307 assert(res == 1 || (errno == EINTR || errno == ERESTART));
308 } while (res != 1);
311 return err;
314 /* Replace spawnveg() in libast.so.1. This function is used by ksh to spawn
315 new processes. The library has a build time option to select between
316 several variants of this function based on behaviour of vfork() and
317 posix_spawn() on the system for which the library is being compiled.
318 Unfortunately, Solaris and illumos use the real vfork() variant which does
319 not work correctly with the vfork() -> fork() translation done by Valgrind
320 (see the forksys pre-wrapper for details). Therefore the function is
321 replaced here with an implementation that uses posix_spawn(). This
322 replacement can be removed when a configuration of libast in Solaris and
323 illumos is changed to use the posix_spawn() implementation.
325 pid_t VG_REPLACE_FUNCTION_ZU(libastZdsoZd1, spawnveg)(const char *command,
326 char **argv,
327 char **envv,
328 pid_t pgid);
329 pid_t VG_REPLACE_FUNCTION_ZU(libastZdsoZd1, spawnveg)(const char *command,
330 char **argv,
331 char **envp,
332 pid_t pgid)
334 int err = 0;
335 pid_t pid;
336 posix_spawnattr_t attr;
337 int attr_init_done = 0;
339 err = posix_spawnattr_init(&attr);
340 if (err != 0)
341 goto out;
342 attr_init_done = 1;
344 err = posix_spawnattr_init(&attr);
345 if (err != 0)
346 goto out;
348 if (pgid != 0) {
349 if (pgid <= 1)
350 pgid = 0;
351 err = posix_spawnattr_setpgroup(&attr, pgid);
352 if (err != 0)
353 goto out;
354 err = posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETPGROUP);
355 if (err != 0)
356 goto out;
359 err = posix_spawn(&pid, command, NULL, &attr, argv, envp ? envp : environ);
361 out:
362 if (attr_init_done)
363 posix_spawnattr_destroy(&attr);
364 if (err != 0) {
365 errno = err;
366 return -1;
368 return pid;
371 #else
372 # error Unknown OS
373 #endif
375 /*--------------------------------------------------------------------*/
376 /*--- end ---*/
377 /*--------------------------------------------------------------------*/