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