1f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 2f76d27a697a7b0bf3b84490baf60623fc96a23afnjn/*--------------------------------------------------------------------*/ 3f76d27a697a7b0bf3b84490baf60623fc96a23afnjn/*--- Launching valgrind launcher-darwin.c ---*/ 4f76d27a697a7b0bf3b84490baf60623fc96a23afnjn/*--------------------------------------------------------------------*/ 5f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 6f76d27a697a7b0bf3b84490baf60623fc96a23afnjn/* 7f76d27a697a7b0bf3b84490baf60623fc96a23afnjn This file is part of Valgrind, a dynamic binary instrumentation 8f76d27a697a7b0bf3b84490baf60623fc96a23afnjn framework. 9f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 10ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes Copyright (C) 2000-2017 Julian Seward 11f76d27a697a7b0bf3b84490baf60623fc96a23afnjn jseward@acm.org 12f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 13f76d27a697a7b0bf3b84490baf60623fc96a23afnjn This program is free software; you can redistribute it and/or 14f76d27a697a7b0bf3b84490baf60623fc96a23afnjn modify it under the terms of the GNU General Public License as 15f76d27a697a7b0bf3b84490baf60623fc96a23afnjn published by the Free Software Foundation; either version 2 of the 16f76d27a697a7b0bf3b84490baf60623fc96a23afnjn License, or (at your option) any later version. 17f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 18f76d27a697a7b0bf3b84490baf60623fc96a23afnjn This program is distributed in the hope that it will be useful, but 19f76d27a697a7b0bf3b84490baf60623fc96a23afnjn WITHOUT ANY WARRANTY; without even the implied warranty of 20f76d27a697a7b0bf3b84490baf60623fc96a23afnjn MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21f76d27a697a7b0bf3b84490baf60623fc96a23afnjn General Public License for more details. 22f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 23f76d27a697a7b0bf3b84490baf60623fc96a23afnjn You should have received a copy of the GNU General Public License 24f76d27a697a7b0bf3b84490baf60623fc96a23afnjn along with this program; if not, write to the Free Software 25f76d27a697a7b0bf3b84490baf60623fc96a23afnjn Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 26f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 02111-1307, USA. 27f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 28f76d27a697a7b0bf3b84490baf60623fc96a23afnjn The GNU General Public License is contained in the file COPYING. 29f76d27a697a7b0bf3b84490baf60623fc96a23afnjn*/ 30f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 31f76d27a697a7b0bf3b84490baf60623fc96a23afnjn/* Note: this is a "normal" program and not part of Valgrind proper, 32f76d27a697a7b0bf3b84490baf60623fc96a23afnjn and so it doesn't have to conform to Valgrind's arcane rules on 33f76d27a697a7b0bf3b84490baf60623fc96a23afnjn no-glibc-usage etc. */ 34f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 35f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include <assert.h> 36f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include <ctype.h> 37f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include <errno.h> 38f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include <fcntl.h> 39f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include <libgen.h> 40f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include <stdarg.h> 41f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include <stdio.h> 42f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include <stdlib.h> 43f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include <string.h> 44f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include <sys/mman.h> 45f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include <sys/param.h> 46f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include <sys/stat.h> 47f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include <sys/user.h> 48f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include <unistd.h> 49f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include <mach-o/fat.h> 50f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include <mach-o/loader.h> 51f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 52f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include "pub_core_debuglog.h" 53a192dafc5336c5e586dfce6c4e6d3f7e82aef266njn#include "pub_core_vki.h" // Avoids warnings from pub_core_libcfile.h 54f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include "pub_core_libcproc.h" // For VALGRIND_LIB, VALGRIND_LAUNCHER 55f76d27a697a7b0bf3b84490baf60623fc96a23afnjn#include "pub_core_ume.h" 56f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 57f76d27a697a7b0bf3b84490baf60623fc96a23afnjnstatic struct { 58f76d27a697a7b0bf3b84490baf60623fc96a23afnjn cpu_type_t cputype; 59f76d27a697a7b0bf3b84490baf60623fc96a23afnjn const char *apple_name; // e.g. x86_64 60f76d27a697a7b0bf3b84490baf60623fc96a23afnjn const char *valgrind_name; // e.g. amd64 61f76d27a697a7b0bf3b84490baf60623fc96a23afnjn} valid_archs[] = { 629893a7540814a6d987e981d265d2aad6b4d27547sewardj { CPU_TYPE_X86, "i386", "x86" }, 639893a7540814a6d987e981d265d2aad6b4d27547sewardj { CPU_TYPE_X86_64, "x86_64", "amd64" }, 649893a7540814a6d987e981d265d2aad6b4d27547sewardj { CPU_TYPE_ARM, "arm", "arm" }, 659893a7540814a6d987e981d265d2aad6b4d27547sewardj /* Not that it's actually relevant, since we don't support PPC on 669893a7540814a6d987e981d265d2aad6b4d27547sewardj MacOS X, but .. the Apple PPC descriptors refer to the BE 679893a7540814a6d987e981d265d2aad6b4d27547sewardj variant, since the LE variant is something that appeared long 689893a7540814a6d987e981d265d2aad6b4d27547sewardj after Apple dropped PPC. */ 699893a7540814a6d987e981d265d2aad6b4d27547sewardj { CPU_TYPE_POWERPC, "ppc", "ppc32" }, 709893a7540814a6d987e981d265d2aad6b4d27547sewardj { CPU_TYPE_POWERPC64, "ppc64", "ppc64be" } 71f76d27a697a7b0bf3b84490baf60623fc96a23afnjn}; 72f76d27a697a7b0bf3b84490baf60623fc96a23afnjnstatic int valid_archs_count = sizeof(valid_archs)/sizeof(valid_archs[0]); 73f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 74f76d27a697a7b0bf3b84490baf60623fc96a23afnjnstatic const char *name_for_cputype(cpu_type_t cputype) 75f76d27a697a7b0bf3b84490baf60623fc96a23afnjn{ 76f76d27a697a7b0bf3b84490baf60623fc96a23afnjn int i; 77f76d27a697a7b0bf3b84490baf60623fc96a23afnjn for (i = 0; i < valid_archs_count; i++) { 78f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (valid_archs[i].cputype == cputype) { 79f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return valid_archs[i].valgrind_name; 80f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 81f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 82f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return NULL; 83f76d27a697a7b0bf3b84490baf60623fc96a23afnjn} 84f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 85f76d27a697a7b0bf3b84490baf60623fc96a23afnjn/* Report fatal errors */ 86f76d27a697a7b0bf3b84490baf60623fc96a23afnjn__attribute__((noreturn)) 87f76d27a697a7b0bf3b84490baf60623fc96a23afnjnstatic void barf ( const char *format, ... ) 88f76d27a697a7b0bf3b84490baf60623fc96a23afnjn{ 89f76d27a697a7b0bf3b84490baf60623fc96a23afnjn va_list vargs; 90f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 91f76d27a697a7b0bf3b84490baf60623fc96a23afnjn va_start(vargs, format); 92f76d27a697a7b0bf3b84490baf60623fc96a23afnjn fprintf(stderr, "valgrind: "); 93f76d27a697a7b0bf3b84490baf60623fc96a23afnjn vfprintf(stderr, format, vargs); 94f76d27a697a7b0bf3b84490baf60623fc96a23afnjn fprintf(stderr, "\n"); 95f76d27a697a7b0bf3b84490baf60623fc96a23afnjn va_end(vargs); 96f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 97f76d27a697a7b0bf3b84490baf60623fc96a23afnjn exit(1); 98f76d27a697a7b0bf3b84490baf60623fc96a23afnjn /*NOTREACHED*/ 99f76d27a697a7b0bf3b84490baf60623fc96a23afnjn assert(0); 100f76d27a697a7b0bf3b84490baf60623fc96a23afnjn} 101f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 102f76d27a697a7b0bf3b84490baf60623fc96a23afnjn/* Search the path for the client program */ 103f76d27a697a7b0bf3b84490baf60623fc96a23afnjnstatic const char *find_client(const char *clientname) 104f76d27a697a7b0bf3b84490baf60623fc96a23afnjn{ 105f76d27a697a7b0bf3b84490baf60623fc96a23afnjn static char fullname[PATH_MAX]; 106f76d27a697a7b0bf3b84490baf60623fc96a23afnjn const char *path = getenv("PATH"); 107f76d27a697a7b0bf3b84490baf60623fc96a23afnjn const char *colon; 108f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 109f76d27a697a7b0bf3b84490baf60623fc96a23afnjn while (path) 110f76d27a697a7b0bf3b84490baf60623fc96a23afnjn { 111f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if ((colon = strchr(path, ':')) == NULL) 112f76d27a697a7b0bf3b84490baf60623fc96a23afnjn { 113f76d27a697a7b0bf3b84490baf60623fc96a23afnjn strcpy(fullname, path); 114f76d27a697a7b0bf3b84490baf60623fc96a23afnjn path = NULL; 115f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 116f76d27a697a7b0bf3b84490baf60623fc96a23afnjn else 117f76d27a697a7b0bf3b84490baf60623fc96a23afnjn { 118f76d27a697a7b0bf3b84490baf60623fc96a23afnjn memcpy(fullname, path, colon - path); 119f76d27a697a7b0bf3b84490baf60623fc96a23afnjn fullname[colon - path] = '\0'; 120f76d27a697a7b0bf3b84490baf60623fc96a23afnjn path = colon + 1; 121f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 122f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 123f76d27a697a7b0bf3b84490baf60623fc96a23afnjn strcat(fullname, "/"); 124f76d27a697a7b0bf3b84490baf60623fc96a23afnjn strcat(fullname, clientname); 125f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 126f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (access(fullname, R_OK|X_OK) == 0) 127f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return fullname; 128f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 129f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 130f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return clientname; 131f76d27a697a7b0bf3b84490baf60623fc96a23afnjn} 132f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 133f76d27a697a7b0bf3b84490baf60623fc96a23afnjnstatic int fat_has_cputype(struct fat_header *fh, cpu_type_t cputype) 134f76d27a697a7b0bf3b84490baf60623fc96a23afnjn{ 135f76d27a697a7b0bf3b84490baf60623fc96a23afnjn struct fat_arch *fa = (struct fat_arch *)(fh+1); 136f76d27a697a7b0bf3b84490baf60623fc96a23afnjn uint32_t nfat_arch = ntohl(fh->nfat_arch); 137f76d27a697a7b0bf3b84490baf60623fc96a23afnjn uint32_t i; 138f76d27a697a7b0bf3b84490baf60623fc96a23afnjn for (i = 0; i < nfat_arch; i++) { 139f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (ntohl(fa[i].cputype) == cputype) return 1; 140f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 141f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return 0; 142f76d27a697a7b0bf3b84490baf60623fc96a23afnjn} 143f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 144f76d27a697a7b0bf3b84490baf60623fc96a23afnjn/* Examine the client and work out which arch it is for */ 145a192dafc5336c5e586dfce6c4e6d3f7e82aef266njnstatic const char *select_arch( 146a192dafc5336c5e586dfce6c4e6d3f7e82aef266njn const char *clientname, cpu_type_t default_cputype, 147a192dafc5336c5e586dfce6c4e6d3f7e82aef266njn const char *default_arch) 148f76d27a697a7b0bf3b84490baf60623fc96a23afnjn{ 149f76d27a697a7b0bf3b84490baf60623fc96a23afnjn uint8_t buf[4096]; 150f76d27a697a7b0bf3b84490baf60623fc96a23afnjn ssize_t bytes; 151f76d27a697a7b0bf3b84490baf60623fc96a23afnjn int fd = open(find_client(clientname), O_RDONLY); 152f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (fd < 0) { 153f76d27a697a7b0bf3b84490baf60623fc96a23afnjn barf("%s: %s", clientname, strerror(errno)); 154f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 155f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 156cc7b218c195fab0c0b9e9f02951c992aa6b66208njn bytes = read(fd, buf, sizeof(buf)); 157cc7b218c195fab0c0b9e9f02951c992aa6b66208njn close(fd); 158f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (bytes != sizeof(buf)) { 159f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return NULL; 160f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 161f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 162f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // If it's thin, return that arch. 163f76d27a697a7b0bf3b84490baf60623fc96a23afnjn { 164f76d27a697a7b0bf3b84490baf60623fc96a23afnjn struct mach_header *mh = (struct mach_header *)buf; 165f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (mh->magic == MH_MAGIC || mh->magic == MH_MAGIC_64) { 166f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return name_for_cputype(mh->cputype); 167f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } else if (mh->magic == MH_CIGAM || mh->magic == MH_CIGAM_64) { 168f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return name_for_cputype(OSSwapInt32(mh->cputype)); 169f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 170f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 171f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 172f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // If it's fat, look for a good arch. 173f76d27a697a7b0bf3b84490baf60623fc96a23afnjn { 174f76d27a697a7b0bf3b84490baf60623fc96a23afnjn struct fat_header *fh = (struct fat_header *)buf; 175f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (ntohl(fh->magic) == FAT_MAGIC) { 176f76d27a697a7b0bf3b84490baf60623fc96a23afnjn uint32_t nfat_arch = ntohl(fh->nfat_arch); 177f76d27a697a7b0bf3b84490baf60623fc96a23afnjn int i; 178f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // If only one fat arch, use it. 179f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (nfat_arch == 1) { 180f76d27a697a7b0bf3b84490baf60623fc96a23afnjn struct fat_arch *fa = (struct fat_arch *)(fh+1); 181f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return name_for_cputype(ntohl(fa->cputype)); 182f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 183f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // Scan fat headers for default arch. 184f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (fat_has_cputype(fh, default_cputype)) { 185f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return default_arch; 186f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 187f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 188f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // Scan fat headers for any supported arch. 189f76d27a697a7b0bf3b84490baf60623fc96a23afnjn for (i = 0; i < valid_archs_count; i++) { 190f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (fat_has_cputype(fh, valid_archs[i].cputype)) { 191f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return valid_archs[i].valgrind_name; 192f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 193f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 194f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 195f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 196f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 197f76d27a697a7b0bf3b84490baf60623fc96a23afnjn return NULL; 198f76d27a697a7b0bf3b84490baf60623fc96a23afnjn} 199f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 200f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 201f76d27a697a7b0bf3b84490baf60623fc96a23afnjn/* Where we expect to find all our aux files */ 202f76d27a697a7b0bf3b84490baf60623fc96a23afnjnstatic const char *valgrind_lib; 203f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 204f76d27a697a7b0bf3b84490baf60623fc96a23afnjnint main(int argc, char** argv, char** envp) 205f76d27a697a7b0bf3b84490baf60623fc96a23afnjn{ 206f76d27a697a7b0bf3b84490baf60623fc96a23afnjn int i, j, loglevel; 207f76d27a697a7b0bf3b84490baf60623fc96a23afnjn const char *toolname = NULL; 208f76d27a697a7b0bf3b84490baf60623fc96a23afnjn const char *clientname = NULL; 209f76d27a697a7b0bf3b84490baf60623fc96a23afnjn int clientname_arg = 0; 210f76d27a697a7b0bf3b84490baf60623fc96a23afnjn const char *archname = NULL; 211f76d27a697a7b0bf3b84490baf60623fc96a23afnjn const char *arch; 212f76d27a697a7b0bf3b84490baf60623fc96a23afnjn const char *default_arch; 213f76d27a697a7b0bf3b84490baf60623fc96a23afnjn cpu_type_t default_cputype; 214f76d27a697a7b0bf3b84490baf60623fc96a23afnjn char *toolfile; 215f76d27a697a7b0bf3b84490baf60623fc96a23afnjn char launcher_name[PATH_MAX+1]; 216f76d27a697a7b0bf3b84490baf60623fc96a23afnjn char* new_line; 217f76d27a697a7b0bf3b84490baf60623fc96a23afnjn char* set_cwd; 218f76d27a697a7b0bf3b84490baf60623fc96a23afnjn char* cwd; 219f76d27a697a7b0bf3b84490baf60623fc96a23afnjn char** new_env; 220f76d27a697a7b0bf3b84490baf60623fc96a23afnjn char **new_argv; 221f76d27a697a7b0bf3b84490baf60623fc96a23afnjn int new_argc; 222f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 223f76d27a697a7b0bf3b84490baf60623fc96a23afnjn /* Start the debugging-log system ASAP. First find out how many 224f76d27a697a7b0bf3b84490baf60623fc96a23afnjn "-d"s were specified. This is a pre-scan of the command line. 225f76d27a697a7b0bf3b84490baf60623fc96a23afnjn At the same time, look for the tool name. */ 226f76d27a697a7b0bf3b84490baf60623fc96a23afnjn loglevel = 0; 227f76d27a697a7b0bf3b84490baf60623fc96a23afnjn for (i = 1; i < argc; i++) { 228f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (argv[i][0] != '-') { 229f76d27a697a7b0bf3b84490baf60623fc96a23afnjn clientname = argv[i]; 230f76d27a697a7b0bf3b84490baf60623fc96a23afnjn clientname_arg = i; 231f76d27a697a7b0bf3b84490baf60623fc96a23afnjn break; 232f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 233f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (0 == strcmp(argv[i], "--")) { 234f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (i+1 < argc) { 235f76d27a697a7b0bf3b84490baf60623fc96a23afnjn clientname = argv[i+1]; 236f76d27a697a7b0bf3b84490baf60623fc96a23afnjn clientname_arg = i; 237f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 238f76d27a697a7b0bf3b84490baf60623fc96a23afnjn break; 239f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 240f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (0 == strcmp(argv[i], "-d")) 241f76d27a697a7b0bf3b84490baf60623fc96a23afnjn loglevel++; 242f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (0 == strncmp(argv[i], "--tool=", 7)) 243f76d27a697a7b0bf3b84490baf60623fc96a23afnjn toolname = argv[i] + 7; 244f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (0 == strncmp(argv[i], "--arch=", 7)) 245f76d27a697a7b0bf3b84490baf60623fc96a23afnjn archname = argv[i] + 7; 246f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 247f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 248f76d27a697a7b0bf3b84490baf60623fc96a23afnjn /* ... and start the debug logger. Now we can safely emit logging 249f76d27a697a7b0bf3b84490baf60623fc96a23afnjn messages all through startup. */ 250f76d27a697a7b0bf3b84490baf60623fc96a23afnjn VG_(debugLog_startup)(loglevel, "Stage 1"); 251f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 252f76d27a697a7b0bf3b84490baf60623fc96a23afnjn /* Make sure we know which tool we're using */ 253f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (toolname) { 254f76d27a697a7b0bf3b84490baf60623fc96a23afnjn VG_(debugLog)(1, "launcher", "tool '%s' requested\n", toolname); 255f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } else { 256f76d27a697a7b0bf3b84490baf60623fc96a23afnjn VG_(debugLog)(1, "launcher", 257f76d27a697a7b0bf3b84490baf60623fc96a23afnjn "no tool requested, defaulting to 'memcheck'\n"); 258f76d27a697a7b0bf3b84490baf60623fc96a23afnjn toolname = "memcheck"; 259f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 260f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 261f76d27a697a7b0bf3b84490baf60623fc96a23afnjn /* Find the real executable if clientname is an app bundle. */ 262f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (clientname) { 263f76d27a697a7b0bf3b84490baf60623fc96a23afnjn struct stat st; 264f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (0 == stat(clientname, &st) && (st.st_mode & S_IFDIR)) { 265f76d27a697a7b0bf3b84490baf60623fc96a23afnjn char *copy = strdup(clientname); 266f76d27a697a7b0bf3b84490baf60623fc96a23afnjn char *appname = basename(copy); 267f76d27a697a7b0bf3b84490baf60623fc96a23afnjn char *dot = strrchr(appname, '.'); 268f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (dot) { 269f76d27a697a7b0bf3b84490baf60623fc96a23afnjn char *newclient; 270f76d27a697a7b0bf3b84490baf60623fc96a23afnjn *dot = '\0'; 271f76d27a697a7b0bf3b84490baf60623fc96a23afnjn asprintf(&newclient, "%s/Contents/MacOS/%s", clientname, appname); 272f76d27a697a7b0bf3b84490baf60623fc96a23afnjn VG_(debugLog)(1, "launcher", "Using executable in app bundle: %s\n", newclient); 273f76d27a697a7b0bf3b84490baf60623fc96a23afnjn clientname = newclient; 274f76d27a697a7b0bf3b84490baf60623fc96a23afnjn argv[clientname_arg] = newclient; 275f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 276f76d27a697a7b0bf3b84490baf60623fc96a23afnjn free(copy); 277f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 278f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 279f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 280f76d27a697a7b0bf3b84490baf60623fc96a23afnjn /* Establish the correct VALGRIND_LIB. */ 281f76d27a697a7b0bf3b84490baf60623fc96a23afnjn { const char *cp; 282f76d27a697a7b0bf3b84490baf60623fc96a23afnjn cp = getenv(VALGRIND_LIB); 283f76d27a697a7b0bf3b84490baf60623fc96a23afnjn valgrind_lib = ( cp == NULL ? VG_LIBDIR : cp ); 284cde90d34fbe5c867c96cca64955d3037fbb06441njn VG_(debugLog)(1, "launcher", "valgrind_lib = %s\n", valgrind_lib); 285f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 286f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 287f76d27a697a7b0bf3b84490baf60623fc96a23afnjn /* Find installed architectures. Use vgpreload_core-<platform>.so as the 288f76d27a697a7b0bf3b84490baf60623fc96a23afnjn * indicator of whether the platform is installed. */ 289f76d27a697a7b0bf3b84490baf60623fc96a23afnjn for (i = 0; i < valid_archs_count; i++) { 290f76d27a697a7b0bf3b84490baf60623fc96a23afnjn char *vgpreload_core; 291f76d27a697a7b0bf3b84490baf60623fc96a23afnjn asprintf(&vgpreload_core, "%s/vgpreload_core-%s-darwin.so", valgrind_lib, valid_archs[i].valgrind_name); 292f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (access(vgpreload_core, R_OK|X_OK) != 0) { 293f76d27a697a7b0bf3b84490baf60623fc96a23afnjn VG_(debugLog)(1, "launcher", "arch '%s' IS NOT installed\n", valid_archs[i].valgrind_name); 2948df59971f203df33ee0b18c17e18873ef2fcfefcrhyskidd memset(&valid_archs[i], 0, sizeof(valid_archs[i])); 295f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } else { 296f76d27a697a7b0bf3b84490baf60623fc96a23afnjn VG_(debugLog)(1, "launcher", "arch '%s' IS installed\n", valid_archs[i].valgrind_name); 297f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 298f76d27a697a7b0bf3b84490baf60623fc96a23afnjn free(vgpreload_core); 299f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 300f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 301f76d27a697a7b0bf3b84490baf60623fc96a23afnjn /* Find the "default" arch (VGCONF_ARCH_PRI from configure). 302f76d27a697a7b0bf3b84490baf60623fc96a23afnjn This is the preferred arch from fat files and the fallback. */ 303f76d27a697a7b0bf3b84490baf60623fc96a23afnjn default_arch = NULL; 304f76d27a697a7b0bf3b84490baf60623fc96a23afnjn default_cputype = 0; 305f76d27a697a7b0bf3b84490baf60623fc96a23afnjn for (i = 0; i < valid_archs_count; i++) { 306f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (!valid_archs[i].cputype) continue; 307f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (0 == strncmp(VG_PLATFORM, valid_archs[i].valgrind_name, 308f76d27a697a7b0bf3b84490baf60623fc96a23afnjn strlen(valid_archs[i].valgrind_name))) 309f76d27a697a7b0bf3b84490baf60623fc96a23afnjn { 310f76d27a697a7b0bf3b84490baf60623fc96a23afnjn default_arch = valid_archs[i].valgrind_name; 311f76d27a697a7b0bf3b84490baf60623fc96a23afnjn default_cputype = valid_archs[i].cputype; 312f76d27a697a7b0bf3b84490baf60623fc96a23afnjn break; 313f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 314f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 315f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (i == valid_archs_count) barf("Unknown/uninstalled VG_PLATFORM '%s'", VG_PLATFORM); 316f76d27a697a7b0bf3b84490baf60623fc96a23afnjn assert(NULL != default_arch); 317f76d27a697a7b0bf3b84490baf60623fc96a23afnjn assert(0 != default_cputype); 318f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 319f76d27a697a7b0bf3b84490baf60623fc96a23afnjn /* Work out what arch to use, or use the default arch if not possible. */ 320f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (archname != NULL) { 321f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // --arch from command line 322f76d27a697a7b0bf3b84490baf60623fc96a23afnjn arch = NULL; 323f76d27a697a7b0bf3b84490baf60623fc96a23afnjn for (i = 0; i < valid_archs_count; i++) { 324f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (0 == strcmp(archname, valid_archs[i].apple_name) || 325f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 0 == strcmp(archname, valid_archs[i].valgrind_name)) 326f76d27a697a7b0bf3b84490baf60623fc96a23afnjn { 327f76d27a697a7b0bf3b84490baf60623fc96a23afnjn arch = valid_archs[i].valgrind_name; 328f76d27a697a7b0bf3b84490baf60623fc96a23afnjn break; 329f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 330f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 331f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (i == valid_archs_count) barf("Unknown --arch '%s'", archname); 332f76d27a697a7b0bf3b84490baf60623fc96a23afnjn assert(NULL != arch); 333f76d27a697a7b0bf3b84490baf60623fc96a23afnjn VG_(debugLog)(1, "launcher", "using arch '%s' from --arch=%s\n", 334f76d27a697a7b0bf3b84490baf60623fc96a23afnjn arch, archname); 335f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 336f76d27a697a7b0bf3b84490baf60623fc96a23afnjn else if (clientname == NULL) { 337f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // no client executable; use default as fallback 338f76d27a697a7b0bf3b84490baf60623fc96a23afnjn VG_(debugLog)(1, "launcher", 339f76d27a697a7b0bf3b84490baf60623fc96a23afnjn "no client specified, defaulting arch to '%s'\n", 340f76d27a697a7b0bf3b84490baf60623fc96a23afnjn default_arch); 341f76d27a697a7b0bf3b84490baf60623fc96a23afnjn arch = default_arch; 342f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 343f76d27a697a7b0bf3b84490baf60623fc96a23afnjn else if ((arch = select_arch(clientname, default_cputype,default_arch))) { 344f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // arch from client executable 345f76d27a697a7b0bf3b84490baf60623fc96a23afnjn VG_(debugLog)(1, "launcher", "selected arch '%s'\n", arch); 346f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 347f76d27a697a7b0bf3b84490baf60623fc96a23afnjn else { 348f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // nothing found in client executable; use default as fallback 349f76d27a697a7b0bf3b84490baf60623fc96a23afnjn VG_(debugLog)(1, "launcher", 350f76d27a697a7b0bf3b84490baf60623fc96a23afnjn "no arch detected, defaulting arch to '%s'\n", 351f76d27a697a7b0bf3b84490baf60623fc96a23afnjn default_arch); 352f76d27a697a7b0bf3b84490baf60623fc96a23afnjn arch = default_arch; 353f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 354f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 355f76d27a697a7b0bf3b84490baf60623fc96a23afnjn cwd = getcwd(NULL, 0); 356f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (!cwd) barf("Current directory no longer exists."); 357f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 358f76d27a697a7b0bf3b84490baf60623fc96a23afnjn /* Figure out the name of this executable (viz, the launcher), so 359f76d27a697a7b0bf3b84490baf60623fc96a23afnjn we can tell stage2. stage2 will use the name for recursive 360ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes invocations of valgrind on child processes. */ 361f76d27a697a7b0bf3b84490baf60623fc96a23afnjn memset(launcher_name, 0, PATH_MAX+1); 362f76d27a697a7b0bf3b84490baf60623fc96a23afnjn for (i = 0; envp[i]; i++) 363f76d27a697a7b0bf3b84490baf60623fc96a23afnjn ; /* executable path is after last envp item */ 364f76d27a697a7b0bf3b84490baf60623fc96a23afnjn /* envp[i] == NULL ; envp[i+1] == executable_path */ 365f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (envp[i+1][0] != '/') { 366f76d27a697a7b0bf3b84490baf60623fc96a23afnjn strcpy(launcher_name, cwd); 367f76d27a697a7b0bf3b84490baf60623fc96a23afnjn strcat(launcher_name, "/"); 368f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 369f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (strlen(launcher_name) + strlen(envp[i+1]) > PATH_MAX) 370f76d27a697a7b0bf3b84490baf60623fc96a23afnjn barf("launcher path is too long"); 371f76d27a697a7b0bf3b84490baf60623fc96a23afnjn strcat(launcher_name, envp[i+1]); 372f76d27a697a7b0bf3b84490baf60623fc96a23afnjn VG_(debugLog)(1, "launcher", "launcher_name = %s\n", launcher_name); 373f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 374f76d27a697a7b0bf3b84490baf60623fc96a23afnjn /* tediously augment the env: VALGRIND_LAUNCHER=launcher_name */ 375f76d27a697a7b0bf3b84490baf60623fc96a23afnjn asprintf(&new_line, VALGRIND_LAUNCHER "=%s", launcher_name); 376f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 377f76d27a697a7b0bf3b84490baf60623fc96a23afnjn /* tediously augment the env: VALGRIND_STARTUP_PWD_%PID_XYZZY=current_working_dir */ 378f76d27a697a7b0bf3b84490baf60623fc96a23afnjn asprintf(&set_cwd, "VALGRIND_STARTUP_PWD_%u_XYZZY=%s", getppid(), cwd); 379f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 380f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // Note that Apple binaries get a secret fourth arg, "char* apple", which 381f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // contains the executable path. Don't forget about it. 382f76d27a697a7b0bf3b84490baf60623fc96a23afnjn for (j = 0; envp[j]; j++) 383f76d27a697a7b0bf3b84490baf60623fc96a23afnjn ; 384f76d27a697a7b0bf3b84490baf60623fc96a23afnjn new_env = malloc((j+4) * sizeof(char*)); 385f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (new_env == NULL) 386f76d27a697a7b0bf3b84490baf60623fc96a23afnjn barf("malloc of new_env failed."); 387f76d27a697a7b0bf3b84490baf60623fc96a23afnjn for (i = 0; i < j; i++) 388f76d27a697a7b0bf3b84490baf60623fc96a23afnjn new_env[i] = envp[i]; 389f76d27a697a7b0bf3b84490baf60623fc96a23afnjn new_env[i++] = new_line; 390f76d27a697a7b0bf3b84490baf60623fc96a23afnjn new_env[i++] = set_cwd; 391f76d27a697a7b0bf3b84490baf60623fc96a23afnjn new_env[i++] = NULL; 392f76d27a697a7b0bf3b84490baf60623fc96a23afnjn new_env[i ] = envp[i-2]; // the 'apple' arg == the executable_path 393f76d27a697a7b0bf3b84490baf60623fc96a23afnjn assert(i == j+3); 394f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 395f76d27a697a7b0bf3b84490baf60623fc96a23afnjn /* tediously edit env: hide dyld options from valgrind's captive dyld */ 396f76d27a697a7b0bf3b84490baf60623fc96a23afnjn for (i = 0; envp[i]; i++) { 397f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (0 == strncmp(envp[i], "DYLD_", 5)) { 398f76d27a697a7b0bf3b84490baf60623fc96a23afnjn envp[i][0] = 'V'; /* VYLD_; changed back by initimg-darwin */ 399f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 400f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 401f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 402f76d27a697a7b0bf3b84490baf60623fc96a23afnjn /* tediously edit argv: remove --arch= */ 403f76d27a697a7b0bf3b84490baf60623fc96a23afnjn new_argv = malloc((1+argc) * sizeof(char *)); 404f76d27a697a7b0bf3b84490baf60623fc96a23afnjn for (i = 0, new_argc = 0; i < argc; i++) { 405f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (0 == strncmp(argv[i], "--arch=", 7)) { 406f76d27a697a7b0bf3b84490baf60623fc96a23afnjn // skip 407f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } else { 408f76d27a697a7b0bf3b84490baf60623fc96a23afnjn new_argv[new_argc++] = argv[i]; 409f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 410f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 411f76d27a697a7b0bf3b84490baf60623fc96a23afnjn new_argv[new_argc++] = NULL; 412f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 413ed39800a83baf5bffbe391f3974eb2af0f415f80Elliott Hughes /* Build the stage2 invocation, and execve it. Bye! */ 414f76d27a697a7b0bf3b84490baf60623fc96a23afnjn asprintf(&toolfile, "%s/%s-%s-darwin", valgrind_lib, toolname, arch); 415f76d27a697a7b0bf3b84490baf60623fc96a23afnjn if (access(toolfile, R_OK|X_OK) != 0) { 416f76d27a697a7b0bf3b84490baf60623fc96a23afnjn barf("tool '%s' not installed (%s) (%s)", toolname, toolfile, strerror(errno)); 417f76d27a697a7b0bf3b84490baf60623fc96a23afnjn } 418f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 419f76d27a697a7b0bf3b84490baf60623fc96a23afnjn VG_(debugLog)(1, "launcher", "launching %s\n", toolfile); 420f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 421f76d27a697a7b0bf3b84490baf60623fc96a23afnjn execve(toolfile, new_argv, new_env); 422f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 423f76d27a697a7b0bf3b84490baf60623fc96a23afnjn fprintf(stderr, "valgrind: failed to start tool '%s' for platform '%s-darwin': %s\n", 424f76d27a697a7b0bf3b84490baf60623fc96a23afnjn toolname, arch, strerror(errno)); 425f76d27a697a7b0bf3b84490baf60623fc96a23afnjn 426f76d27a697a7b0bf3b84490baf60623fc96a23afnjn exit(1); 427f76d27a697a7b0bf3b84490baf60623fc96a23afnjn} 428