1
2/*--------------------------------------------------------------------*/
3/*--- Client-space code for the core.               vg_preloaded.c ---*/
4/*--------------------------------------------------------------------*/
5
6/*
7   This file is part of Valgrind, a dynamic binary instrumentation
8   framework.
9
10   Copyright (C) 2000-2010 Julian Seward
11      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/* ---------------------------------------------------------------------
33   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.
43   ------------------------------------------------------------------ */
44
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
49
50#if defined(VGO_linux) || defined(VGO_aix5)
51
52/* ---------------------------------------------------------------------
53   Hook for running __libc_freeres once the program exits.
54   ------------------------------------------------------------------ */
55
56void VG_NOTIFY_ON_LOAD(freeres)( void );
57void VG_NOTIFY_ON_LOAD(freeres)( void )
58{
59   int res;
60#if !defined(__UCLIBC__) && !defined(VGO_aix5) && !defined(ANDROID)
61   extern void __libc_freeres(void);
62   __libc_freeres();
63#endif
64   VALGRIND_DO_CLIENT_REQUEST(res, 0 /* default */,
65                              VG_USERREQ__LIBC_FREERES_DONE,
66                              0, 0, 0, 0, 0);
67   /*NOTREACHED*/
68   *(volatile int *)0 = 'x';
69}
70
71/* ---------------------------------------------------------------------
72   Wrapper for indirect functions which need to be redirected.
73   ------------------------------------------------------------------ */
74
75void * VG_NOTIFY_ON_LOAD(ifunc_wrapper) (void);
76void * VG_NOTIFY_ON_LOAD(ifunc_wrapper) (void)
77{
78    OrigFn fn;
79    Addr result = 0;
80    int res;
81
82    /* Call the original indirect function and get it's result */
83    VALGRIND_GET_ORIG_FN(fn);
84    CALL_FN_W_v(result, fn);
85
86    /* Ask the valgrind core running on the real CPU (as opposed to this
87       code which runs on the emulated CPU) to update the redirection that
88       led to this function. This client request eventually gives control to
89       the function VG_(redir_add_ifunc_target) in m_redir.c  */
90    VALGRIND_DO_CLIENT_REQUEST(res, 0,
91                               VG_USERREQ__ADD_IFUNC_TARGET,
92                               fn.nraddr, result, 0, 0, 0);
93    return (void*)result;
94}
95
96#elif defined(VGO_darwin)
97
98#include "config.h" /* VERSION */
99
100/* ---------------------------------------------------------------------
101   Darwin crash log hints
102   ------------------------------------------------------------------ */
103
104/* This string will be inserted into crash logs, so crashes while
105   running under Valgrind can be distinguished from other crashes. */
106__private_extern__ char *__crashreporter_info__ = "Instrumented by Valgrind " VERSION;
107
108/* ---------------------------------------------------------------------
109   Darwin environment cleanup
110   ------------------------------------------------------------------ */
111
112/* Scrubbing DYLD_INSERT_LIBRARIES from envp during exec is insufficient,
113   as there are other ways to launch a process with environment that
114   valgrind can't catch easily (i.e. launchd).
115   Instead, scrub DYLD_INSERT_LIBRARIES from the parent process once
116   dyld is done loading vg_preload.so.
117*/
118#include <string.h>
119#include <crt_externs.h>
120
121// GrP fixme copied from m_libcproc
122static void env_unsetenv ( Char **env, const Char *varname )
123{
124   Char **from;
125   Char **to = NULL;
126   Int len = strlen(varname);
127
128   for (from = to = env; from && *from; from++) {
129      if (!(strncmp(varname, *from, len) == 0 && (*from)[len] == '=')) {
130	 *to = *from;
131	 to++;
132      }
133   }
134   *(to++) = *(from++);
135   /* fix the 4th "char* apple" pointer (aka. executable path pointer) */
136   *(to++) = *(from++);
137   *to = NULL;
138}
139
140static void vg_cleanup_env(void)  __attribute__((constructor));
141static void vg_cleanup_env(void)
142{
143    Char **envp = (Char**)*_NSGetEnviron();
144    env_unsetenv(envp, "VALGRIND_LAUNCHER");
145    env_unsetenv(envp, "DYLD_SHARED_REGION");
146    // GrP fixme should be more like mash_colon_env()
147    env_unsetenv(envp, "DYLD_INSERT_LIBRARIES");
148}
149
150/* ---------------------------------------------------------------------
151   Darwin arc4random (rdar://6166275)
152   ------------------------------------------------------------------ */
153
154#include <fcntl.h>
155#include <unistd.h>
156
157int VG_REPLACE_FUNCTION_ZU(libSystemZdZaZddylib, arc4random)(void);
158int VG_REPLACE_FUNCTION_ZU(libSystemZdZaZddylib, arc4random)(void)
159{
160    static int rnd = -1;
161    int result;
162
163    if (rnd < 0) rnd = open("/dev/random", O_RDONLY);
164
165    read(rnd, &result, sizeof(result));
166    return result;
167}
168
169void VG_REPLACE_FUNCTION_ZU(libSystemZdZaZddylib, arc4random_stir)(void);
170void VG_REPLACE_FUNCTION_ZU(libSystemZdZaZddylib, arc4random_stir)(void)
171{
172    // do nothing
173}
174
175void VG_REPLACE_FUNCTION_ZU(libSystemZdZaZddylib, arc4random_addrandom)(unsigned char *dat, int datlen);
176void VG_REPLACE_FUNCTION_ZU(libSystemZdZaZddylib, arc4random_addrandom)(unsigned char *dat, int datlen)
177{
178    // do nothing
179    // GrP fixme ought to check [dat..dat+datlen) is defined
180    // but don't care if it's initialized
181}
182
183#else
184
185#  error Unknown OS
186#endif
187
188/*--------------------------------------------------------------------*/
189/*--- end                                                          ---*/
190/*--------------------------------------------------------------------*/
191