Home | History | Annotate | Download | only in coregrind
      1 
      2 /*--------------------------------------------------------------------*/
      3 /*--- Process-related libc stuff.                     m_libcproc.c ---*/
      4 /*--------------------------------------------------------------------*/
      5 
      6 /*
      7    This file is part of Valgrind, a dynamic binary instrumentation
      8    framework.
      9 
     10    Copyright (C) 2000-2011 Julian Seward
     11       jseward (at) 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 #include "pub_core_basics.h"
     32 #include "pub_core_vki.h"
     33 #include "pub_core_vkiscnums.h"
     34 #include "pub_core_libcbase.h"
     35 #include "pub_core_libcassert.h"
     36 #include "pub_core_libcfile.h"
     37 #include "pub_core_libcprint.h"
     38 #include "pub_core_libcproc.h"
     39 #include "pub_core_libcsignal.h"
     40 #include "pub_core_tooliface.h"
     41 #include "pub_core_options.h"
     42 #include "pub_core_seqmatch.h"
     43 #include "pub_core_mallocfree.h"
     44 #include "pub_core_syscall.h"
     45 #include "pub_core_xarray.h"
     46 #include "pub_core_clientstate.h"
     47 
     48 #if defined(VGO_darwin)
     49 /* --- !!! --- EXTERNAL HEADERS start --- !!! --- */
     50 #include <mach/mach.h>   /* mach_thread_self */
     51 /* --- !!! --- EXTERNAL HEADERS end --- !!! --- */
     52 #endif
     53 
     54 /* IMPORTANT: on Darwin it is essential to use the _nocancel versions
     55    of syscalls rather than the vanilla version, if a _nocancel version
     56    is available.  See docs/internals/Darwin-notes.txt for the reason
     57    why. */
     58 
     59 /* ---------------------------------------------------------------------
     60    Command line and environment stuff
     61    ------------------------------------------------------------------ */
     62 
     63 /* As deduced from sp_at_startup, the client's argc, argv[] and
     64    envp[] as extracted from the client's stack at startup-time. */
     65 Char** VG_(client_envp) = NULL;
     66 
     67 /* Path to library directory */
     68 const Char *VG_(libdir) = VG_LIBDIR;
     69 
     70 const Char *VG_(LD_PRELOAD_var_name) =
     71 #if defined(VGO_linux)
     72    "LD_PRELOAD";
     73 #elif defined(VGO_darwin)
     74    "DYLD_INSERT_LIBRARIES";
     75 #else
     76 #  error Unknown OS
     77 #endif
     78 
     79 /* We do getenv without libc's help by snooping around in
     80    VG_(client_envp) as determined at startup time. */
     81 Char *VG_(getenv)(Char *varname)
     82 {
     83    Int i, n;
     84    vg_assert( VG_(client_envp) );
     85    n = VG_(strlen)(varname);
     86    for (i = 0; VG_(client_envp)[i] != NULL; i++) {
     87       Char* s = VG_(client_envp)[i];
     88       if (VG_(strncmp)(varname, s, n) == 0 && s[n] == '=') {
     89          return & s[n+1];
     90       }
     91    }
     92    return NULL;
     93 }
     94 
     95 void  VG_(env_unsetenv) ( Char **env, const Char *varname )
     96 {
     97    Char **from, **to;
     98    vg_assert(env);
     99    vg_assert(varname);
    100    to = NULL;
    101    Int len = VG_(strlen)(varname);
    102 
    103    for (from = to = env; from && *from; from++) {
    104       if (!(VG_(strncmp)(varname, *from, len) == 0 && (*from)[len] == '=')) {
    105 	 *to = *from;
    106 	 to++;
    107       }
    108    }
    109    *to = *from;
    110 }
    111 
    112 /* set the environment; returns the old env if a new one was allocated */
    113 Char **VG_(env_setenv) ( Char ***envp, const Char* varname, const Char *val )
    114 {
    115    Char **env = (*envp);
    116    Char **cpp;
    117    Int len = VG_(strlen)(varname);
    118    Char *valstr = VG_(arena_malloc)(VG_AR_CORE, "libcproc.es.1",
    119                                     len + VG_(strlen)(val) + 2);
    120    Char **oldenv = NULL;
    121 
    122    VG_(sprintf)(valstr, "%s=%s", varname, val);
    123 
    124    for (cpp = env; cpp && *cpp; cpp++) {
    125       if (VG_(strncmp)(varname, *cpp, len) == 0 && (*cpp)[len] == '=') {
    126 	 *cpp = valstr;
    127 	 return oldenv;
    128       }
    129    }
    130 
    131    if (env == NULL) {
    132       env = VG_(arena_malloc)(VG_AR_CORE, "libcproc.es.2", sizeof(Char **) * 2);
    133       env[0] = valstr;
    134       env[1] = NULL;
    135 
    136       *envp = env;
    137 
    138    }  else {
    139       Int envlen = (cpp-env) + 2;
    140       Char **newenv = VG_(arena_malloc)(VG_AR_CORE, "libcproc.es.3",
    141                                         envlen * sizeof(Char **));
    142 
    143       for (cpp = newenv; *env; )
    144 	 *cpp++ = *env++;
    145       *cpp++ = valstr;
    146       *cpp++ = NULL;
    147 
    148       oldenv = *envp;
    149 
    150       *envp = newenv;
    151    }
    152 
    153    return oldenv;
    154 }
    155 
    156 
    157 /* Walk through a colon-separated environment variable, and remove the
    158    entries which match remove_pattern.  It slides everything down over
    159    the removed entries, and pads the remaining space with '\0'.  It
    160    modifies the entries in place (in the client address space), but it
    161    shouldn't matter too much, since we only do this just before an
    162    execve().
    163 
    164    This is also careful to mop up any excess ':'s, since empty strings
    165    delimited by ':' are considered to be '.' in a path.
    166 */
    167 static void mash_colon_env(Char *varp, const Char *remove_pattern)
    168 {
    169    Char *const start = varp;
    170    Char *entry_start = varp;
    171    Char *output = varp;
    172 
    173    if (varp == NULL)
    174       return;
    175 
    176    while(*varp) {
    177       if (*varp == ':') {
    178 	 Char prev;
    179 	 Bool match;
    180 
    181 	 /* This is a bit subtle: we want to match against the entry
    182 	    we just copied, because it may have overlapped with
    183 	    itself, junking the original. */
    184 
    185 	 prev = *output;
    186 	 *output = '\0';
    187 
    188 	 match = VG_(string_match)(remove_pattern, entry_start);
    189 
    190 	 *output = prev;
    191 
    192 	 if (match) {
    193 	    output = entry_start;
    194 	    varp++;			/* skip ':' after removed entry */
    195 	 } else
    196 	    entry_start = output+1;	/* entry starts after ':' */
    197       }
    198 
    199       if (*varp)
    200          *output++ = *varp++;
    201    }
    202 
    203    /* make sure last entry is nul terminated */
    204    *output = '\0';
    205 
    206    /* match against the last entry */
    207    if (VG_(string_match)(remove_pattern, entry_start)) {
    208       output = entry_start;
    209       if (output > start) {
    210 	 /* remove trailing ':' */
    211 	 output--;
    212 	 vg_assert(*output == ':');
    213       }
    214    }
    215 
    216    /* pad out the left-overs with '\0' */
    217    while(output < varp)
    218       *output++ = '\0';
    219 }
    220 
    221 
    222 // Removes all the Valgrind-added stuff from the passed environment.  Used
    223 // when starting child processes, so they don't see that added stuff.
    224 void VG_(env_remove_valgrind_env_stuff)(Char** envp)
    225 {
    226 
    227 #if defined(VGO_darwin)
    228 
    229    // Environment cleanup is also handled during parent launch
    230    // in vg_preloaded.c:vg_cleanup_env().
    231 
    232 #endif
    233 
    234    Int i;
    235    Char* ld_preload_str = NULL;
    236    Char* ld_library_path_str = NULL;
    237    Char* dyld_insert_libraries_str = NULL;
    238    Char* buf;
    239 
    240    // Find LD_* variables
    241    // DDD: should probably conditionally compiled some of this:
    242    // - LD_LIBRARY_PATH is universal?
    243    // - LD_PRELOAD is on Linux, not on Darwin, not sure about AIX
    244    // - DYLD_INSERT_LIBRARIES and DYLD_SHARED_REGION are Darwin-only
    245    for (i = 0; envp[i] != NULL; i++) {
    246       if (VG_(strncmp)(envp[i], "LD_PRELOAD=", 11) == 0)
    247          ld_preload_str = VG_(arena_strdup)(VG_AR_CORE, "libcproc.erves.1", &envp[i][11]);
    248       if (VG_(strncmp)(envp[i], "LD_LIBRARY_PATH=", 16) == 0)
    249          ld_library_path_str = VG_(arena_strdup)(VG_AR_CORE, "libcproc.erves.2", &envp[i][16]);
    250       if (VG_(strncmp)(envp[i], "DYLD_INSERT_LIBRARIES=", 22) == 0)
    251          dyld_insert_libraries_str = VG_(arena_strdup)(VG_AR_CORE, "libcproc.erves.3", &envp[i][22]);
    252    }
    253 
    254    buf = VG_(arena_malloc)(VG_AR_CORE, "libcproc.erves.4",
    255                            VG_(strlen)(VG_(libdir)) + 20);
    256 
    257    // Remove Valgrind-specific entries from LD_*.
    258    VG_(sprintf)(buf, "%s*/vgpreload_*.so", VG_(libdir));
    259    mash_colon_env(ld_preload_str, buf);
    260    mash_colon_env(dyld_insert_libraries_str, buf);
    261    VG_(sprintf)(buf, "%s*", VG_(libdir));
    262    mash_colon_env(ld_library_path_str, buf);
    263 
    264    // Remove VALGRIND_LAUNCHER variable.
    265    VG_(env_unsetenv)(envp, VALGRIND_LAUNCHER);
    266 
    267    // Remove DYLD_SHARED_REGION variable.
    268    VG_(env_unsetenv)(envp, "DYLD_SHARED_REGION");
    269 
    270    // XXX if variable becomes empty, remove it completely?
    271 
    272    VG_(arena_free)(VG_AR_CORE, buf);
    273 }
    274 
    275 /* ---------------------------------------------------------------------
    276    Various important syscall wrappers
    277    ------------------------------------------------------------------ */
    278 
    279 Int VG_(waitpid)(Int pid, Int *status, Int options)
    280 {
    281 #  if defined(VGO_linux)
    282    SysRes res = VG_(do_syscall4)(__NR_wait4,
    283                                  pid, (UWord)status, options, 0);
    284    return sr_isError(res) ? -1 : sr_Res(res);
    285 #  elif defined(VGO_darwin)
    286    SysRes res = VG_(do_syscall4)(__NR_wait4_nocancel,
    287                                  pid, (UWord)status, options, 0);
    288    return sr_isError(res) ? -1 : sr_Res(res);
    289 #  else
    290 #    error Unknown OS
    291 #  endif
    292 }
    293 
    294 /* clone the environment */
    295 Char **VG_(env_clone) ( Char **oldenv )
    296 {
    297    Char **oldenvp;
    298    Char **newenvp;
    299    Char **newenv;
    300    Int  envlen;
    301 
    302    vg_assert(oldenv);
    303    for (oldenvp = oldenv; oldenvp && *oldenvp; oldenvp++);
    304 
    305    envlen = oldenvp - oldenv + 1;
    306 
    307    newenv = VG_(arena_malloc)(VG_AR_CORE, "libcproc.ec.1",
    308                               envlen * sizeof(Char **));
    309 
    310    oldenvp = oldenv;
    311    newenvp = newenv;
    312 
    313    while (oldenvp && *oldenvp) {
    314       *newenvp++ = *oldenvp++;
    315    }
    316 
    317    *newenvp = *oldenvp;
    318 
    319    return newenv;
    320 }
    321 
    322 void VG_(execv) ( Char* filename, Char** argv )
    323 {
    324    Char** envp;
    325    SysRes res;
    326 
    327    /* restore the DATA rlimit for the child */
    328    VG_(setrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
    329 
    330    envp = VG_(env_clone)(VG_(client_envp));
    331    VG_(env_remove_valgrind_env_stuff)( envp );
    332 
    333    res = VG_(do_syscall3)(__NR_execve,
    334                           (UWord)filename, (UWord)argv, (UWord)envp);
    335 
    336    VG_(printf)("EXEC failed, errno = %lld\n", (Long)sr_Err(res));
    337 }
    338 
    339 /* Return -1 if error, else 0.  NOTE does not indicate return code of
    340    child! */
    341 Int VG_(system) ( Char* cmd )
    342 {
    343    Int pid;
    344    if (cmd == NULL)
    345       return 1;
    346    pid = VG_(fork)();
    347    if (pid < 0)
    348       return -1;
    349    if (pid == 0) {
    350       /* child */
    351       Char* argv[4] = { "/bin/sh", "-c", cmd, 0 };
    352       VG_(execv)(argv[0], argv);
    353 
    354       /* If we're still alive here, execve failed. */
    355       VG_(exit)(1);
    356    } else {
    357       /* parent */
    358       /* We have to set SIGCHLD to its default behaviour in order that
    359          VG_(waitpid) works (at least on AIX).  According to the Linux
    360          man page for waitpid:
    361 
    362          POSIX.1-2001 specifies that if the disposition of SIGCHLD is
    363          set to SIG_IGN or the SA_NOCLDWAIT flag is set for SIGCHLD
    364          (see sigaction(2)), then children that terminate do not
    365          become zombies and a call to wait() or waitpid() will block
    366          until all children have terminated, and then fail with errno
    367          set to ECHILD.  (The original POSIX standard left the
    368          behaviour of setting SIGCHLD to SIG_IGN unspecified.)
    369       */
    370       Int ir, zzz;
    371       vki_sigaction_toK_t sa, sa2;
    372       vki_sigaction_fromK_t saved_sa;
    373       VG_(memset)( &sa, 0, sizeof(sa) );
    374       VG_(sigemptyset)(&sa.sa_mask);
    375       sa.ksa_handler = VKI_SIG_DFL;
    376       sa.sa_flags    = 0;
    377       ir = VG_(sigaction)(VKI_SIGCHLD, &sa, &saved_sa);
    378       vg_assert(ir == 0);
    379 
    380       zzz = VG_(waitpid)(pid, NULL, 0);
    381 
    382       VG_(convert_sigaction_fromK_to_toK)( &saved_sa, &sa2 );
    383       ir = VG_(sigaction)(VKI_SIGCHLD, &sa2, NULL);
    384       vg_assert(ir == 0);
    385       return zzz == -1 ? -1 : 0;
    386    }
    387 }
    388 
    389 /* ---------------------------------------------------------------------
    390    Resource limits
    391    ------------------------------------------------------------------ */
    392 
    393 /* Support for getrlimit. */
    394 Int VG_(getrlimit) (Int resource, struct vki_rlimit *rlim)
    395 {
    396    SysRes res = VG_(mk_SysRes_Error)(VKI_ENOSYS);
    397    /* res = getrlimit( resource, rlim ); */
    398 #  ifdef __NR_ugetrlimit
    399    res = VG_(do_syscall2)(__NR_ugetrlimit, resource, (UWord)rlim);
    400 #  endif
    401    if (sr_isError(res) && sr_Err(res) == VKI_ENOSYS)
    402       res = VG_(do_syscall2)(__NR_getrlimit, resource, (UWord)rlim);
    403    return sr_isError(res) ? -1 : sr_Res(res);
    404 }
    405 
    406 
    407 /* Support for setrlimit. */
    408 Int VG_(setrlimit) (Int resource, const struct vki_rlimit *rlim)
    409 {
    410    SysRes res;
    411    /* res = setrlimit( resource, rlim ); */
    412    res = VG_(do_syscall2)(__NR_setrlimit, resource, (UWord)rlim);
    413    return sr_isError(res) ? -1 : sr_Res(res);
    414 }
    415 
    416 /* Support for prctl. */
    417 Int VG_(prctl) (Int option,
    418                 ULong arg2, ULong arg3, ULong arg4, ULong arg5)
    419 {
    420    SysRes res = VG_(mk_SysRes_Error)(VKI_ENOSYS);
    421 #  if defined(VGO_linux)
    422    /* res = prctl( option, arg2, arg3, arg4, arg5 ); */
    423    res = VG_(do_syscall5)(__NR_prctl, (UWord) option,
    424                           (UWord) arg2, (UWord) arg3, (UWord) arg4,
    425                           (UWord) arg5);
    426 #  endif
    427 
    428    return sr_isError(res) ? -1 : sr_Res(res);
    429 }
    430 
    431 /* ---------------------------------------------------------------------
    432    pids, etc
    433    ------------------------------------------------------------------ */
    434 
    435 Int VG_(gettid)(void)
    436 {
    437 #  if defined(VGO_linux)
    438    SysRes res = VG_(do_syscall0)(__NR_gettid);
    439 
    440    if (sr_isError(res) && sr_Res(res) == VKI_ENOSYS) {
    441       Char pid[16];
    442       /*
    443        * The gettid system call does not exist. The obvious assumption
    444        * to make at this point would be that we are running on an older
    445        * system where the getpid system call actually returns the ID of
    446        * the current thread.
    447        *
    448        * Unfortunately it seems that there are some systems with a kernel
    449        * where getpid has been changed to return the ID of the thread group
    450        * leader but where the gettid system call has not yet been added.
    451        *
    452        * So instead of calling getpid here we use readlink to see where
    453        * the /proc/self link is pointing...
    454        */
    455 
    456       res = VG_(do_syscall3)(__NR_readlink, (UWord)"/proc/self",
    457                              (UWord)pid, sizeof(pid));
    458       if (!sr_isError(res) && sr_Res(res) > 0) {
    459          Char* s;
    460          pid[sr_Res(res)] = '\0';
    461          res = VG_(mk_SysRes_Success)(  VG_(strtoll10)(pid, &s) );
    462          if (*s != '\0') {
    463             VG_(message)(Vg_DebugMsg,
    464                "Warning: invalid file name linked to by /proc/self: %s\n",
    465                pid);
    466          }
    467       }
    468    }
    469 
    470    return sr_Res(res);
    471 
    472 #  elif defined(VGO_darwin)
    473    // Darwin's gettid syscall is something else.
    474    // Use Mach thread ports for lwpid instead.
    475    return mach_thread_self();
    476 
    477 #  else
    478 #    error "Unknown OS"
    479 #  endif
    480 }
    481 
    482 /* You'd be amazed how many places need to know the current pid. */
    483 Int VG_(getpid) ( void )
    484 {
    485    /* ASSUMES SYSCALL ALWAYS SUCCEEDS */
    486    return sr_Res( VG_(do_syscall0)(__NR_getpid) );
    487 }
    488 
    489 Int VG_(getpgrp) ( void )
    490 {
    491    /* ASSUMES SYSCALL ALWAYS SUCCEEDS */
    492    return sr_Res( VG_(do_syscall0)(__NR_getpgrp) );
    493 }
    494 
    495 Int VG_(getppid) ( void )
    496 {
    497    /* ASSUMES SYSCALL ALWAYS SUCCEEDS */
    498    return sr_Res( VG_(do_syscall0)(__NR_getppid) );
    499 }
    500 
    501 Int VG_(geteuid) ( void )
    502 {
    503    /* ASSUMES SYSCALL ALWAYS SUCCEEDS */
    504 #  if defined(__NR_geteuid32)
    505    // We use the 32-bit version if it's supported.  Otherwise, IDs greater
    506    // than 65536 cause problems, as bug #151209 showed.
    507    return sr_Res( VG_(do_syscall0)(__NR_geteuid32) );
    508 #  else
    509    return sr_Res( VG_(do_syscall0)(__NR_geteuid) );
    510 #  endif
    511 }
    512 
    513 Int VG_(getegid) ( void )
    514 {
    515    /* ASSUMES SYSCALL ALWAYS SUCCEEDS */
    516 #  if defined(__NR_getegid32)
    517    // We use the 32-bit version if it's supported.  Otherwise, IDs greater
    518    // than 65536 cause problems, as bug #151209 showed.
    519    return sr_Res( VG_(do_syscall0)(__NR_getegid32) );
    520 #  else
    521    return sr_Res( VG_(do_syscall0)(__NR_getegid) );
    522 #  endif
    523 }
    524 
    525 /* Get supplementary groups into list[0 .. size-1].  Returns the
    526    number of groups written, or -1 if error.  Note that in order to be
    527    portable, the groups are 32-bit unsigned ints regardless of the
    528    platform. */
    529 Int VG_(getgroups)( Int size, UInt* list )
    530 {
    531 #  if defined(VGP_x86_linux) || defined(VGP_ppc32_linux)
    532    Int    i;
    533    SysRes sres;
    534    UShort list16[64];
    535    if (size < 0) return -1;
    536    if (size > 64) size = 64;
    537    sres = VG_(do_syscall2)(__NR_getgroups, size, (Addr)list16);
    538    if (sr_isError(sres))
    539       return -1;
    540    if (sr_Res(sres) > size)
    541       return -1;
    542    for (i = 0; i < sr_Res(sres); i++)
    543       list[i] = (UInt)list16[i];
    544    return sr_Res(sres);
    545 
    546 #  elif defined(VGP_amd64_linux) || defined(VGP_ppc64_linux)  \
    547         || defined(VGP_arm_linux)                             \
    548         || defined(VGO_darwin) || defined(VGP_s390x_linux)
    549    SysRes sres;
    550    sres = VG_(do_syscall2)(__NR_getgroups, size, (Addr)list);
    551    if (sr_isError(sres))
    552       return -1;
    553    return sr_Res(sres);
    554 
    555 #  else
    556 #     error "VG_(getgroups): needs implementation on this platform"
    557 #  endif
    558 }
    559 
    560 /* ---------------------------------------------------------------------
    561    Process tracing
    562    ------------------------------------------------------------------ */
    563 
    564 Int VG_(ptrace) ( Int request, Int pid, void *addr, void *data )
    565 {
    566    SysRes res;
    567    res = VG_(do_syscall4)(__NR_ptrace, request, pid, (UWord)addr, (UWord)data);
    568    if (sr_isError(res))
    569       return -1;
    570    return sr_Res(res);
    571 }
    572 
    573 /* ---------------------------------------------------------------------
    574    Fork
    575    ------------------------------------------------------------------ */
    576 
    577 Int VG_(fork) ( void )
    578 {
    579 #  if defined(VGO_linux)
    580    SysRes res;
    581    res = VG_(do_syscall0)(__NR_fork);
    582    if (sr_isError(res))
    583       return -1;
    584    return sr_Res(res);
    585 
    586 #  elif defined(VGO_darwin)
    587    SysRes res;
    588    res = VG_(do_syscall0)(__NR_fork); /* __NR_fork is UX64 */
    589    if (sr_isError(res))
    590       return -1;
    591    /* on success: wLO = child pid; wHI = 1 for child, 0 for parent */
    592    if (sr_ResHI(res) != 0) {
    593       return 0;  /* this is child: return 0 instead of child pid */
    594    }
    595    return sr_Res(res);
    596 
    597 #  else
    598 #    error "Unknown OS"
    599 #  endif
    600 }
    601 
    602 /* ---------------------------------------------------------------------
    603    Timing stuff
    604    ------------------------------------------------------------------ */
    605 
    606 UInt VG_(read_millisecond_timer) ( void )
    607 {
    608    /* 'now' and 'base' are in microseconds */
    609    static ULong base = 0;
    610    ULong  now;
    611 
    612 #  if defined(VGO_linux)
    613    { SysRes res;
    614      struct vki_timespec ts_now;
    615      res = VG_(do_syscall2)(__NR_clock_gettime, VKI_CLOCK_MONOTONIC,
    616                             (UWord)&ts_now);
    617      if (sr_isError(res) == 0) {
    618         now = ts_now.tv_sec * 1000000ULL + ts_now.tv_nsec / 1000;
    619      } else {
    620        struct vki_timeval tv_now;
    621        res = VG_(do_syscall2)(__NR_gettimeofday, (UWord)&tv_now, (UWord)NULL);
    622        vg_assert(! sr_isError(res));
    623        now = tv_now.tv_sec * 1000000ULL + tv_now.tv_usec;
    624      }
    625    }
    626 
    627 #  elif defined(VGO_darwin)
    628    // Weird: it seems that gettimeofday() doesn't fill in the timeval, but
    629    // rather returns the tv_sec as the low 32 bits of the result and the
    630    // tv_usec as the high 32 bits of the result.  (But the timeval cannot be
    631    // NULL!)  See bug 200990.
    632    { SysRes res;
    633      struct vki_timeval tv_now = { 0, 0 };
    634      res = VG_(do_syscall2)(__NR_gettimeofday, (UWord)&tv_now, (UWord)NULL);
    635      vg_assert(! sr_isError(res));
    636      now = sr_Res(res) * 1000000ULL + sr_ResHI(res);
    637    }
    638 
    639 #  else
    640 #    error "Unknown OS"
    641 #  endif
    642 
    643    /* COMMON CODE */
    644    if (base == 0)
    645       base = now;
    646 
    647    return (now - base) / 1000;
    648 }
    649 
    650 
    651 /* ---------------------------------------------------------------------
    652    atfork()
    653    ------------------------------------------------------------------ */
    654 
    655 struct atfork {
    656    vg_atfork_t  pre;
    657    vg_atfork_t  parent;
    658    vg_atfork_t  child;
    659 };
    660 
    661 #define VG_MAX_ATFORK 10
    662 
    663 static struct atfork atforks[VG_MAX_ATFORK];
    664 static Int n_atfork = 0;
    665 
    666 void VG_(atfork)(vg_atfork_t pre, vg_atfork_t parent, vg_atfork_t child)
    667 {
    668    Int i;
    669 
    670    for (i = 0; i < n_atfork; i++) {
    671       if (atforks[i].pre == pre &&
    672           atforks[i].parent == parent &&
    673           atforks[i].child == child)
    674          return;
    675    }
    676 
    677    if (n_atfork >= VG_MAX_ATFORK)
    678       VG_(core_panic)(
    679          "Too many VG_(atfork) handlers requested: raise VG_MAX_ATFORK");
    680 
    681    atforks[n_atfork].pre    = pre;
    682    atforks[n_atfork].parent = parent;
    683    atforks[n_atfork].child  = child;
    684 
    685    n_atfork++;
    686 }
    687 
    688 void VG_(do_atfork_pre)(ThreadId tid)
    689 {
    690    Int i;
    691 
    692    for (i = 0; i < n_atfork; i++)
    693       if (atforks[i].pre != NULL)
    694          (*atforks[i].pre)(tid);
    695 }
    696 
    697 void VG_(do_atfork_parent)(ThreadId tid)
    698 {
    699    Int i;
    700 
    701    for (i = 0; i < n_atfork; i++)
    702       if (atforks[i].parent != NULL)
    703          (*atforks[i].parent)(tid);
    704 }
    705 
    706 // Defined in m_main.c
    707 void print_preamble(Bool logging_to_fd, const char* toolname);
    708 
    709 Char* VG_(clo_log_fname_unexpanded) = NULL;
    710 Char* VG_(clo_xml_fname_unexpanded) = NULL;
    711 
    712 // If --log-file=ABC%pXYZ is specified, we'd like to have separate log files
    713 // for each forked child.
    714 // If %p is present in the --log-file option, this function creates
    715 // a new log file and redirects the child's output to it.
    716 static void open_new_logfile_for_forked_child(void)
    717 {
    718    Int tmp_fd = -1;
    719 
    720    if (VG_(log_output_sink).is_socket == False && VG_(clo_log_fname_unexpanded) != NULL) {
    721      tmp_fd = reopen_output_fd(False);
    722      VG_(log_output_sink).fd = VG_(safe_fd)(tmp_fd);
    723    }
    724 
    725    if (VG_(xml_output_sink).is_socket == False && VG_(clo_xml_fname_unexpanded) != NULL) {
    726      tmp_fd = reopen_output_fd(True);
    727      VG_(xml_output_sink).fd = VG_(safe_fd)(tmp_fd);
    728    }
    729 
    730    print_preamble(False, NULL);
    731 }
    732 
    733 void VG_(do_atfork_child)(ThreadId tid)
    734 {
    735    Int i;
    736 
    737    open_new_logfile_for_forked_child();
    738 
    739    for (i = 0; i < n_atfork; i++)
    740       if (atforks[i].child != NULL)
    741          (*atforks[i].child)(tid);
    742 }
    743 
    744 
    745 /*--------------------------------------------------------------------*/
    746 /*--- end                                                          ---*/
    747 /*--------------------------------------------------------------------*/
    748