drd/tests: Fix remaining gcc 8 compiler warnings
[valgrind.git] / coregrind / vg_preloaded.c
blobad033432ab0bbe83f5a1305351c76da74058fb6e
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, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
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) || defined(VGO_solaris)
52 /* ---------------------------------------------------------------------
53 Hook for running __gnu_cxx::__freeres() and __libc_freeres() once
54 the program exits.
55 ------------------------------------------------------------------ */
57 void VG_NOTIFY_ON_LOAD(freeres)(Vg_FreeresToRun to_run);
58 void VG_NOTIFY_ON_LOAD(freeres)(Vg_FreeresToRun to_run)
60 # if !defined(__UCLIBC__) && !defined(MUSL_LIBC) \
61 && !defined(VGPV_arm_linux_android) \
62 && !defined(VGPV_x86_linux_android) \
63 && !defined(VGPV_mips32_linux_android) \
64 && !defined(VGPV_arm64_linux_android)
66 /* g++ mangled __gnu_cxx::__freeres yields -> _ZN9__gnu_cxx9__freeresEv */
67 extern void _ZN9__gnu_cxx9__freeresEv(void) __attribute__((weak));
68 if (((to_run & VG_RUN__GNU_CXX__FREERES) != 0) &&
69 (_ZN9__gnu_cxx9__freeresEv != NULL)) {
70 _ZN9__gnu_cxx9__freeresEv();
73 # if defined(VGO_linux)
74 /* __libc_freeres() not yet available on Solaris. */
75 extern void __libc_freeres(void);
76 if ((to_run & VG_RUN__LIBC_FREERES) != 0) {
77 __libc_freeres();
79 # endif
80 # endif
82 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__FREERES_DONE, 0, 0, 0, 0, 0);
83 /*NOTREACHED*/
84 *(volatile int *)0 = 'x';
87 #endif // VGO_linux || VGO_solaris
89 #if defined(VGO_linux)
91 /* ---------------------------------------------------------------------
92 Wrapper for indirect functions which need to be redirected.
93 ------------------------------------------------------------------ */
95 void * VG_NOTIFY_ON_LOAD(ifunc_wrapper) (void);
96 void * VG_NOTIFY_ON_LOAD(ifunc_wrapper) (void)
98 OrigFn fn;
99 Addr result = 0;
100 Addr fnentry;
102 /* Call the original indirect function and get it's result */
103 VALGRIND_GET_ORIG_FN(fn);
104 CALL_FN_W_v(result, fn);
106 #if defined(VGP_ppc64be_linux)
107 /* ppc64be uses function descriptors, so get the actual function entry
108 address for the client request, but return the function descriptor
109 from this function.
110 result points to the function descriptor, which starts with the
111 function entry. */
112 fnentry = *(Addr*)result;
113 #else
114 fnentry = result;
115 #endif
117 /* Ask the valgrind core running on the real CPU (as opposed to this
118 code which runs on the emulated CPU) to update the redirection that
119 led to this function. This client request eventually gives control to
120 the function VG_(redir_add_ifunc_target) in m_redir.c */
121 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__ADD_IFUNC_TARGET,
122 fn.nraddr, fnentry, 0, 0, 0);
123 return (void*)result;
126 #elif defined(VGO_darwin)
128 #include "config.h" /* VERSION */
130 /* ---------------------------------------------------------------------
131 Darwin crash log hints
132 ------------------------------------------------------------------ */
134 /* This string will be inserted into crash logs, so crashes while
135 running under Valgrind can be distinguished from other crashes. */
136 __private_extern__ const char *__crashreporter_info__ = "Instrumented by Valgrind " VERSION;
138 /* ---------------------------------------------------------------------
139 Darwin environment cleanup
140 ------------------------------------------------------------------ */
142 /* Scrubbing DYLD_INSERT_LIBRARIES from envp during exec is insufficient,
143 as there are other ways to launch a process with environment that
144 valgrind can't catch easily (i.e. launchd).
145 Instead, scrub DYLD_INSERT_LIBRARIES from the parent process once
146 dyld is done loading vg_preload.so.
148 #include <string.h>
149 #include <crt_externs.h>
151 // GrP fixme copied from m_libcproc
152 static void env_unsetenv ( HChar **env, const HChar *varname )
154 HChar **from;
155 HChar **to = NULL;
156 Int len = strlen(varname);
158 for (from = to = env; from && *from; from++) {
159 if (!(strncmp(varname, *from, len) == 0 && (*from)[len] == '=')) {
160 *to = *from;
161 to++;
164 *(to++) = *(from++);
165 /* fix the 4th "char* apple" pointer (aka. executable path pointer) */
166 *(to++) = *(from++);
167 *to = NULL;
170 static void vg_cleanup_env(void) __attribute__((constructor));
171 static void vg_cleanup_env(void)
173 HChar **envp = (HChar**)*_NSGetEnviron();
174 env_unsetenv(envp, "VALGRIND_LAUNCHER");
175 env_unsetenv(envp, "DYLD_SHARED_REGION");
176 // GrP fixme should be more like mash_colon_env()
177 env_unsetenv(envp, "DYLD_INSERT_LIBRARIES");
180 /* ---------------------------------------------------------------------
181 Darwin arc4random (rdar://6166275)
182 ------------------------------------------------------------------ */
184 #include <fcntl.h>
185 #include <unistd.h>
187 int VG_REPLACE_FUNCTION_ZU(libSystemZdZaZddylib, arc4random)(void);
188 int VG_REPLACE_FUNCTION_ZU(libSystemZdZaZddylib, arc4random)(void)
190 static int rnd = -1;
191 int result;
193 if (rnd < 0) rnd = open("/dev/random", O_RDONLY);
195 read(rnd, &result, sizeof(result));
196 return result;
199 void VG_REPLACE_FUNCTION_ZU(libSystemZdZaZddylib, arc4random_stir)(void);
200 void VG_REPLACE_FUNCTION_ZU(libSystemZdZaZddylib, arc4random_stir)(void)
202 // do nothing
205 void VG_REPLACE_FUNCTION_ZU(libSystemZdZaZddylib, arc4random_addrandom)(unsigned char *dat, int datlen);
206 void VG_REPLACE_FUNCTION_ZU(libSystemZdZaZddylib, arc4random_addrandom)(unsigned char *dat, int datlen)
208 // do nothing
209 // GrP fixme ought to check [dat..dat+datlen) is defined
210 // but don't care if it's initialized
213 #elif defined(VGO_solaris)
215 /* Declare the errno and environ symbols weakly in case the client is not
216 linked against libc. In such a case it also cannot run replacement
217 functions for set_error() and spawnveg() where these two variables are
218 needed so this is ok. */
219 __attribute__((weak)) extern int errno;
220 __attribute__((weak)) extern char **environ;
222 #include <assert.h>
223 #include <errno.h>
224 #include <spawn.h>
225 #include <sys/syscall.h>
226 #include <sys/signal.h>
227 #include <unistd.h>
229 /* Replace function block_all_signals() from libc. When the client program is
230 not running under valgrind, the function blocks all signals by setting
231 sc_sigblock flag in the schedctl control block. When run under Valgrind
232 this would bypass Valgrind's syscall and signal machinery.
233 Valgrind's signal machinery needs to retain control over which signals are
234 blocked and which not (see m_signals.c and m_scheduler/scheduler.c for more
235 information - typically synchronous signals should not be blocked).
236 Therefore this function replacement emulates lwp_sigmask syscall.
238 void VG_REPLACE_FUNCTION_ZU(VG_Z_LIBC_SONAME, block_all_signals)(/*ulwp_t*/ void *self);
239 void VG_REPLACE_FUNCTION_ZU(VG_Z_LIBC_SONAME, block_all_signals)(/*ulwp_t*/ void *self)
241 syscall(SYS_lwp_sigmask, SIG_SETMASK, ~0U, ~0U, ~0U, ~0U);
244 /* Replace functions get_error() and set_error() in libc. These functions are
245 internal to the library and are used to work with an error value returned
246 by posix_spawn() (when it is implemented using vfork()). A child calls
247 set_error() to set an error code and the parent then calls get_error() to
248 read it. Accessor functions are used so these trivial store+load operations
249 are not changed by the compiler in any way.
251 Since Valgrind translates vfork() to a normal fork(), calling set_error()
252 by the child would have no effect on the error value in the parent so
253 something must be done to fix this problem.
255 A pipe is created between a child and its parent in the forksys pre-wrapper
256 when a vfork() is encountered. The child's end of the pipe is closed when
257 the child exits or execs (because close-on-exec is set on the file
258 descriptor). Valgrind (the parent) waits on the child's end of the pipe to
259 be closed which preserves the vfork() behaviour that the parent process is
260 suspended while the child is using its resources.
262 The pipe is then used to send an eventual error code set by the child in
263 posix_spawn() to the parent. If there is any error Valgrind returns it as
264 an error from the vfork() syscall. This means the syscall can return errors
265 that it would normally never return but this is not a problem in practice
266 because any error is directly propagated as a return code from
267 posix_spawn().
269 Address of vg_vfork_fildes is found by Valgrind when debug information for
270 vgpreload_core.so is being processed. A value of this variable is set in
271 the forksys pre-wrapper before a fork() call is made and set back to -1
272 before returning from the wrapper by the parent.
274 Newer Solaris versions introduce the spawn syscall and posix_spawn() is
275 implemented using it. The redirect is not needed for these versions.
277 int vg_vfork_fildes = -1;
279 int VG_REPLACE_FUNCTION_ZU(VG_Z_LIBC_SONAME, get_error)(int *errp);
280 int VG_REPLACE_FUNCTION_ZU(VG_Z_LIBC_SONAME, get_error)(int *errp)
282 /* Always return 0 when the parent tries to call get_error(). Any error
283 from the child is returned directly as an error from the vfork child.
284 Value pointed by errp is initialized only by the child so not
285 redirecting this function would mean that the parent gets an
286 uninitialized/garbage value when it calls this function. */
287 return 0;
290 int VG_REPLACE_FUNCTION_ZU(VG_Z_LIBC_SONAME, set_error)(int *errp, int err);
291 int VG_REPLACE_FUNCTION_ZU(VG_Z_LIBC_SONAME, set_error)(int *errp, int err)
293 *errp = err;
295 /* Libc should always call set_error() only after doing a vfork() syscall
296 in posix_spawn(). The forksys pre-wrapper saves a descriptor of the
297 child's end of the pipe in vg_vfork_fildes so it is an error if it is
298 not a valid file descriptor at this point. */
299 assert(vg_vfork_fildes >= 0);
300 /* Current protocol between this function and the forksys pre-wrapper
301 allows to send only errors in range [0, 255] (one byte values). */
302 assert(err >= 0 && err <= 0xff);
304 if (err != 0) {
305 unsigned char w = (unsigned char)(err & 0xff);
306 ssize_t res;
307 do {
308 res = write(vg_vfork_fildes, &w, 1);
309 assert(res == 1 || (errno == EINTR || errno == ERESTART));
310 } while (res != 1);
313 return err;
316 /* Replace spawnveg() in libast.so.1. This function is used by ksh to spawn
317 new processes. The library has a build time option to select between
318 several variants of this function based on behaviour of vfork() and
319 posix_spawn() on the system for which the library is being compiled.
320 Unfortunately, Solaris and illumos use the real vfork() variant which does
321 not work correctly with the vfork() -> fork() translation done by Valgrind
322 (see the forksys pre-wrapper for details). Therefore the function is
323 replaced here with an implementation that uses posix_spawn(). This
324 replacement can be removed when a configuration of libast in Solaris and
325 illumos is changed to use the posix_spawn() implementation.
327 pid_t VG_REPLACE_FUNCTION_ZU(libastZdsoZd1, spawnveg)(const char *command,
328 char **argv,
329 char **envv,
330 pid_t pgid);
331 pid_t VG_REPLACE_FUNCTION_ZU(libastZdsoZd1, spawnveg)(const char *command,
332 char **argv,
333 char **envp,
334 pid_t pgid)
336 int err = 0;
337 pid_t pid;
338 posix_spawnattr_t attr;
339 int attr_init_done = 0;
341 err = posix_spawnattr_init(&attr);
342 if (err != 0)
343 goto out;
344 attr_init_done = 1;
346 err = posix_spawnattr_init(&attr);
347 if (err != 0)
348 goto out;
350 if (pgid != 0) {
351 if (pgid <= 1)
352 pgid = 0;
353 err = posix_spawnattr_setpgroup(&attr, pgid);
354 if (err != 0)
355 goto out;
356 err = posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETPGROUP);
357 if (err != 0)
358 goto out;
361 err = posix_spawn(&pid, command, NULL, &attr, argv, envp ? envp : environ);
363 out:
364 if (attr_init_done)
365 posix_spawnattr_destroy(&attr);
366 if (err != 0) {
367 errno = err;
368 return -1;
370 return pid;
373 #else
374 # error Unknown OS
375 #endif
377 /*--------------------------------------------------------------------*/
378 /*--- end ---*/
379 /*--------------------------------------------------------------------*/