blob: 2ea7a7a9bf26a174bf1237bd71f0fd1387d953b3 [file] [log] [blame]
njn16eeb4e2005-06-16 03:56:58 +00001
sewardjcbdddcf2005-03-10 23:23:45 +00002/*--------------------------------------------------------------------*/
njn16eeb4e2005-06-16 03:56:58 +00003/*--- Client-space code for the core. vg_preloaded.c ---*/
sewardjcbdddcf2005-03-10 23:23:45 +00004/*--------------------------------------------------------------------*/
5
6/*
njnc0ae7052005-08-25 22:55:19 +00007 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
sewardjcbdddcf2005-03-10 23:23:45 +00009
sewardjb3a1e4b2015-08-21 11:32:26 +000010 Copyright (C) 2000-2015 Julian Seward
sewardjcbdddcf2005-03-10 23:23:45 +000011 jseward@acm.org
12
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
28 The GNU General Public License is contained in the file COPYING.
29*/
30
31
32/* ---------------------------------------------------------------------
njn16eeb4e2005-06-16 03:56:58 +000033 ALL THE CODE IN THIS FILE RUNS ON THE SIMULATED CPU.
34
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.
39
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.
sewardjcbdddcf2005-03-10 23:23:45 +000043 ------------------------------------------------------------------ */
44
njnc7561b92005-06-19 01:24:32 +000045#include "pub_core_basics.h"
njn93fe3b22005-12-21 20:22:52 +000046#include "pub_core_clreq.h"
njn24a6efb2005-06-20 03:36:51 +000047#include "pub_core_debuginfo.h" // Needed for pub_core_redir.h
48#include "pub_core_redir.h" // For VG_NOTIFY_ON_LOAD
sewardjcbdddcf2005-03-10 23:23:45 +000049
sewardj6e9de462011-06-28 07:25:29 +000050#if defined(VGO_linux)
tomd2645142009-10-29 09:27:11 +000051
sewardjcbdddcf2005-03-10 23:23:45 +000052/* ---------------------------------------------------------------------
53 Hook for running __libc_freeres once the program exits.
54 ------------------------------------------------------------------ */
55
njn16eeb4e2005-06-16 03:56:58 +000056void VG_NOTIFY_ON_LOAD(freeres)( void );
57void VG_NOTIFY_ON_LOAD(freeres)( void )
sewardjcbdddcf2005-03-10 23:23:45 +000058{
philippe5d5dd8e2012-08-05 00:08:25 +000059# if !defined(__UCLIBC__) \
sewardj26ed4192014-11-04 17:44:21 +000060 && !defined(VGPV_arm_linux_android) \
61 && !defined(VGPV_x86_linux_android) \
62 && !defined(VGPV_mips32_linux_android) \
63 && !defined(VGPV_arm64_linux_android)
sewardjcbdddcf2005-03-10 23:23:45 +000064 extern void __libc_freeres(void);
65 __libc_freeres();
sewardj126e82d2011-07-12 13:33:00 +000066# endif
sewardj4b3a7422011-10-24 13:21:57 +000067 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__LIBC_FREERES_DONE,
bart575ce8e2011-05-15 07:04:03 +000068 0, 0, 0, 0, 0);
sewardjcbdddcf2005-03-10 23:23:45 +000069 /*NOTREACHED*/
sewardja6f76ee2010-10-11 19:15:33 +000070 *(volatile int *)0 = 'x';
sewardjcbdddcf2005-03-10 23:23:45 +000071}
72
tomd2645142009-10-29 09:27:11 +000073/* ---------------------------------------------------------------------
74 Wrapper for indirect functions which need to be redirected.
75 ------------------------------------------------------------------ */
76
77void * VG_NOTIFY_ON_LOAD(ifunc_wrapper) (void);
78void * VG_NOTIFY_ON_LOAD(ifunc_wrapper) (void)
79{
80 OrigFn fn;
81 Addr result = 0;
mjwa6838262014-07-15 15:07:01 +000082 Addr fnentry;
tomd2645142009-10-29 09:27:11 +000083
84 /* Call the original indirect function and get it's result */
85 VALGRIND_GET_ORIG_FN(fn);
86 CALL_FN_W_v(result, fn);
87
carlldd690bf2014-08-07 23:49:27 +000088#if defined(VGP_ppc64be_linux)
89 /* ppc64be uses function descriptors, so get the actual function entry
mjwa6838262014-07-15 15:07:01 +000090 address for the client request, but return the function descriptor
philippea83e7d62014-07-17 21:23:09 +000091 from this function.
92 result points to the function descriptor, which starts with the
93 function entry. */
94 fnentry = *(Addr*)result;
mjwa6838262014-07-15 15:07:01 +000095#else
96 fnentry = result;
97#endif
98
tomd2645142009-10-29 09:27:11 +000099 /* 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 */
sewardj4b3a7422011-10-24 13:21:57 +0000103 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__ADD_IFUNC_TARGET,
mjwa6838262014-07-15 15:07:01 +0000104 fn.nraddr, fnentry, 0, 0, 0);
bart431ad282009-11-10 15:11:30 +0000105 return (void*)result;
tomd2645142009-10-29 09:27:11 +0000106}
107
njnf76d27a2009-05-28 01:53:07 +0000108#elif defined(VGO_darwin)
109
bart62e0f3c2009-12-29 17:30:16 +0000110#include "config.h" /* VERSION */
111
njnf76d27a2009-05-28 01:53:07 +0000112/* ---------------------------------------------------------------------
113 Darwin crash log hints
114 ------------------------------------------------------------------ */
115
116/* This string will be inserted into crash logs, so crashes while
117 running under Valgrind can be distinguished from other crashes. */
floriane07cbb32013-01-15 03:19:54 +0000118__private_extern__ const char *__crashreporter_info__ = "Instrumented by Valgrind " VERSION;
njnf76d27a2009-05-28 01:53:07 +0000119
120/* ---------------------------------------------------------------------
121 Darwin environment cleanup
122 ------------------------------------------------------------------ */
123
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.
129*/
130#include <string.h>
131#include <crt_externs.h>
132
133// GrP fixme copied from m_libcproc
florian19f91bb2012-11-10 22:29:54 +0000134static void env_unsetenv ( HChar **env, const HChar *varname )
njnf76d27a2009-05-28 01:53:07 +0000135{
florian19f91bb2012-11-10 22:29:54 +0000136 HChar **from;
137 HChar **to = NULL;
njnf76d27a2009-05-28 01:53:07 +0000138 Int len = strlen(varname);
139
140 for (from = to = env; from && *from; from++) {
141 if (!(strncmp(varname, *from, len) == 0 && (*from)[len] == '=')) {
142 *to = *from;
143 to++;
144 }
145 }
146 *(to++) = *(from++);
147 /* fix the 4th "char* apple" pointer (aka. executable path pointer) */
148 *(to++) = *(from++);
149 *to = NULL;
150}
151
152static void vg_cleanup_env(void) __attribute__((constructor));
153static void vg_cleanup_env(void)
154{
florian19f91bb2012-11-10 22:29:54 +0000155 HChar **envp = (HChar**)*_NSGetEnviron();
njnf76d27a2009-05-28 01:53:07 +0000156 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");
160}
161
162/* ---------------------------------------------------------------------
163 Darwin arc4random (rdar://6166275)
164 ------------------------------------------------------------------ */
165
njnea2d6fd2010-07-01 00:20:20 +0000166#include <fcntl.h>
167#include <unistd.h>
njnf76d27a2009-05-28 01:53:07 +0000168
169int VG_REPLACE_FUNCTION_ZU(libSystemZdZaZddylib, arc4random)(void);
170int VG_REPLACE_FUNCTION_ZU(libSystemZdZaZddylib, arc4random)(void)
171{
njnea2d6fd2010-07-01 00:20:20 +0000172 static int rnd = -1;
njnf76d27a2009-05-28 01:53:07 +0000173 int result;
174
njnea2d6fd2010-07-01 00:20:20 +0000175 if (rnd < 0) rnd = open("/dev/random", O_RDONLY);
176
177 read(rnd, &result, sizeof(result));
njnf76d27a2009-05-28 01:53:07 +0000178 return result;
179}
180
181void VG_REPLACE_FUNCTION_ZU(libSystemZdZaZddylib, arc4random_stir)(void);
182void VG_REPLACE_FUNCTION_ZU(libSystemZdZaZddylib, arc4random_stir)(void)
183{
184 // do nothing
185}
186
187void VG_REPLACE_FUNCTION_ZU(libSystemZdZaZddylib, arc4random_addrandom)(unsigned char *dat, int datlen);
188void VG_REPLACE_FUNCTION_ZU(libSystemZdZaZddylib, arc4random_addrandom)(unsigned char *dat, int datlen)
189{
190 // do nothing
191 // GrP fixme ought to check [dat..dat+datlen) is defined
192 // but don't care if it's initialized
193}
194
sewardj8eb8bab2015-07-21 14:44:28 +0000195#elif defined(VGO_solaris)
njnf76d27a2009-05-28 01:53:07 +0000196
sewardj8eb8bab2015-07-21 14:44:28 +0000197/* 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;
203
204#include <assert.h>
205#include <errno.h>
206#include <spawn.h>
207#include <sys/syscall.h>
208#include <sys/signal.h>
209#include <unistd.h>
210
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.
219*/
220void VG_REPLACE_FUNCTION_ZU(VG_Z_LIBC_SONAME, block_all_signals)(/*ulwp_t*/ void *self);
221void VG_REPLACE_FUNCTION_ZU(VG_Z_LIBC_SONAME, block_all_signals)(/*ulwp_t*/ void *self)
222{
223 syscall(SYS_lwp_sigmask, SIG_SETMASK, ~0U, ~0U, ~0U, ~0U);
224}
225
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.
232
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.
236
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.
243
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
249 posix_spawn().
250
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.
255
256 Newer Solaris versions introduce the spawn syscall and posix_spawn() is
257 implemented using it. The redirect is not needed for these versions.
258*/
259int vg_vfork_fildes = -1;
260
261int VG_REPLACE_FUNCTION_ZU(VG_Z_LIBC_SONAME, get_error)(int *errp);
262int VG_REPLACE_FUNCTION_ZU(VG_Z_LIBC_SONAME, get_error)(int *errp)
263{
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. */
269 return 0;
270}
271
272int VG_REPLACE_FUNCTION_ZU(VG_Z_LIBC_SONAME, set_error)(int *errp, int err);
273int VG_REPLACE_FUNCTION_ZU(VG_Z_LIBC_SONAME, set_error)(int *errp, int err)
274{
275 *errp = err;
276
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);
285
286 if (err != 0) {
287 unsigned char w = (unsigned char)(err & 0xff);
288 ssize_t res;
289 do {
290 res = write(vg_vfork_fildes, &w, 1);
291 assert(res == 1 || (errno == EINTR || errno == ERESTART));
292 } while (res != 1);
293 }
294
295 return err;
296}
297
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.
308*/
309pid_t VG_REPLACE_FUNCTION_ZU(libastZdsoZd1, spawnveg)(const char *command,
310 char **argv,
311 char **envv,
312 pid_t pgid);
313pid_t VG_REPLACE_FUNCTION_ZU(libastZdsoZd1, spawnveg)(const char *command,
314 char **argv,
315 char **envp,
316 pid_t pgid)
317{
318 int err = 0;
319 pid_t pid;
320 posix_spawnattr_t attr;
321 int attr_init_done = 0;
322
323 err = posix_spawnattr_init(&attr);
324 if (err != 0)
325 goto out;
326 attr_init_done = 1;
327
328 err = posix_spawnattr_init(&attr);
329 if (err != 0)
330 goto out;
331
332 if (pgid != 0) {
333 if (pgid <= 1)
334 pgid = 0;
335 err = posix_spawnattr_setpgroup(&attr, pgid);
336 if (err != 0)
337 goto out;
338 err = posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETPGROUP);
339 if (err != 0)
340 goto out;
341 }
342
343 err = posix_spawn(&pid, command, NULL, &attr, argv, envp ? envp : environ);
344
345out:
346 if (attr_init_done)
347 posix_spawnattr_destroy(&attr);
348 if (err != 0) {
349 errno = err;
350 return -1;
351 }
352 return pid;
353}
354
355#else
njnf76d27a2009-05-28 01:53:07 +0000356# error Unknown OS
357#endif
sewardjeb3603e2006-01-24 01:01:17 +0000358
sewardjcbdddcf2005-03-10 23:23:45 +0000359/*--------------------------------------------------------------------*/
njn16eeb4e2005-06-16 03:56:58 +0000360/*--- end ---*/
sewardjcbdddcf2005-03-10 23:23:45 +0000361/*--------------------------------------------------------------------*/