1695dde81fe9ba126d9a1a57cb38dcccf95426e3eflorian/* -*- mode: C; c-basic-offset: 3; -*- */ 245f4e7c91119c7d01a59f5e827c67841632c9314sewardj 345f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*--------------------------------------------------------------------*/ 445f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*--- Launching valgrind m_launcher.c ---*/ 545f4e7c91119c7d01a59f5e827c67841632c9314sewardj/*--------------------------------------------------------------------*/ 645f4e7c91119c7d01a59f5e827c67841632c9314sewardj 745f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* 845f4e7c91119c7d01a59f5e827c67841632c9314sewardj This file is part of Valgrind, a dynamic binary instrumentation 945f4e7c91119c7d01a59f5e827c67841632c9314sewardj framework. 1045f4e7c91119c7d01a59f5e827c67841632c9314sewardj 110f157ddb404bcde7815a1c5bf2d7e41c114f3d73sewardj Copyright (C) 2000-2013 Julian Seward 1245f4e7c91119c7d01a59f5e827c67841632c9314sewardj jseward@acm.org 1345f4e7c91119c7d01a59f5e827c67841632c9314sewardj 1445f4e7c91119c7d01a59f5e827c67841632c9314sewardj This program is free software; you can redistribute it and/or 1545f4e7c91119c7d01a59f5e827c67841632c9314sewardj modify it under the terms of the GNU General Public License as 1645f4e7c91119c7d01a59f5e827c67841632c9314sewardj published by the Free Software Foundation; either version 2 of the 1745f4e7c91119c7d01a59f5e827c67841632c9314sewardj License, or (at your option) any later version. 1845f4e7c91119c7d01a59f5e827c67841632c9314sewardj 1945f4e7c91119c7d01a59f5e827c67841632c9314sewardj This program is distributed in the hope that it will be useful, but 2045f4e7c91119c7d01a59f5e827c67841632c9314sewardj WITHOUT ANY WARRANTY; without even the implied warranty of 2145f4e7c91119c7d01a59f5e827c67841632c9314sewardj MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 2245f4e7c91119c7d01a59f5e827c67841632c9314sewardj General Public License for more details. 2345f4e7c91119c7d01a59f5e827c67841632c9314sewardj 2445f4e7c91119c7d01a59f5e827c67841632c9314sewardj You should have received a copy of the GNU General Public License 2545f4e7c91119c7d01a59f5e827c67841632c9314sewardj along with this program; if not, write to the Free Software 2645f4e7c91119c7d01a59f5e827c67841632c9314sewardj Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 2745f4e7c91119c7d01a59f5e827c67841632c9314sewardj 02111-1307, USA. 2845f4e7c91119c7d01a59f5e827c67841632c9314sewardj 2945f4e7c91119c7d01a59f5e827c67841632c9314sewardj The GNU General Public License is contained in the file COPYING. 3045f4e7c91119c7d01a59f5e827c67841632c9314sewardj*/ 3145f4e7c91119c7d01a59f5e827c67841632c9314sewardj 3245f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Note: this is a "normal" program and not part of Valgrind proper, 3345f4e7c91119c7d01a59f5e827c67841632c9314sewardj and so it doesn't have to conform to Valgrind's arcane rules on 3445f4e7c91119c7d01a59f5e827c67841632c9314sewardj no-glibc-usage etc. */ 3545f4e7c91119c7d01a59f5e827c67841632c9314sewardj 365c46da8ce1e919595193a653584dfae7174b28e0tom/* Include valgrind headers before system headers to avoid problems 375c46da8ce1e919595193a653584dfae7174b28e0tom with the system headers #defining things which are used as names 385c46da8ce1e919595193a653584dfae7174b28e0tom of structure members in vki headers. */ 395c46da8ce1e919595193a653584dfae7174b28e0tom 405c46da8ce1e919595193a653584dfae7174b28e0tom#include "pub_core_debuglog.h" 415c46da8ce1e919595193a653584dfae7174b28e0tom#include "pub_core_vki.h" // Avoids warnings from 425c46da8ce1e919595193a653584dfae7174b28e0tom // pub_core_libcfile.h 435c46da8ce1e919595193a653584dfae7174b28e0tom#include "pub_core_libcproc.h" // For VALGRIND_LIB, VALGRIND_LAUNCHER 445c46da8ce1e919595193a653584dfae7174b28e0tom#include "pub_core_ume.h" 455c46da8ce1e919595193a653584dfae7174b28e0tom 46fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom#include <assert.h> 47fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom#include <ctype.h> 48fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom#include <elf.h> 4945f4e7c91119c7d01a59f5e827c67841632c9314sewardj#include <errno.h> 50fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom#include <fcntl.h> 5145f4e7c91119c7d01a59f5e827c67841632c9314sewardj#include <stdio.h> 5245f4e7c91119c7d01a59f5e827c67841632c9314sewardj#include <stdlib.h> 5345f4e7c91119c7d01a59f5e827c67841632c9314sewardj#include <string.h> 5445f4e7c91119c7d01a59f5e827c67841632c9314sewardj#include <unistd.h> 5545f4e7c91119c7d01a59f5e827c67841632c9314sewardj 56a879a47ce7c2ec18b76ffce49f0e662164539e18tom#ifndef EM_X86_64 5781e60b25fa661addf0a6566486aca909a19bd2c6njn#define EM_X86_64 62 // elf.h doesn't define this on some older systems 5881e60b25fa661addf0a6566486aca909a19bd2c6njn#endif 59a879a47ce7c2ec18b76ffce49f0e662164539e18tom 60f0c1250e324f6684757c6a15545366447ef1d64fsewardj#ifndef EM_AARCH64 61f0c1250e324f6684757c6a15545366447ef1d64fsewardj#define EM_AARCH64 183 // ditto 62f0c1250e324f6684757c6a15545366447ef1d64fsewardj#endif 63f0c1250e324f6684757c6a15545366447ef1d64fsewardj 64ed12bf2b073b1681265e956b7727553f904e5a54sewardj#ifndef EM_PPC64 65ed12bf2b073b1681265e956b7727553f904e5a54sewardj#define EM_PPC64 21 // ditto 66ed12bf2b073b1681265e956b7727553f904e5a54sewardj#endif 67ed12bf2b073b1681265e956b7727553f904e5a54sewardj 68112711afefcfcd43680c7c4aa8d38ef180e8811esewardj#ifndef EM_TILEGX 69112711afefcfcd43680c7c4aa8d38ef180e8811esewardj#define EM_TILEGX 191 70112711afefcfcd43680c7c4aa8d38ef180e8811esewardj#endif 71112711afefcfcd43680c7c4aa8d38ef180e8811esewardj 72fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom/* Report fatal errors */ 738813eef4f290add8e7d66db4deae8cedddcb68bcsewardj__attribute__((noreturn)) 74fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtomstatic void barf ( const char *format, ... ) 7545f4e7c91119c7d01a59f5e827c67841632c9314sewardj{ 76fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom va_list vargs; 77fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom 78fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom va_start(vargs, format); 79fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom fprintf(stderr, "valgrind: Cannot continue: "); 80fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom vfprintf(stderr, format, vargs); 81fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom fprintf(stderr, "\n"); 82fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom va_end(vargs); 83fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom 8445f4e7c91119c7d01a59f5e827c67841632c9314sewardj exit(1); 858813eef4f290add8e7d66db4deae8cedddcb68bcsewardj /*NOTREACHED*/ 868813eef4f290add8e7d66db4deae8cedddcb68bcsewardj assert(0); 8745f4e7c91119c7d01a59f5e827c67841632c9314sewardj} 8845f4e7c91119c7d01a59f5e827c67841632c9314sewardj 89fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom/* Search the path for the client program */ 90fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtomstatic const char *find_client(const char *clientname) 91fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom{ 92b593be39d80165efa84ee5f1fb42adb9f79b6c1fflorian char *fullname; 93fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom const char *path = getenv("PATH"); 94fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom const char *colon; 95fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom 96b593be39d80165efa84ee5f1fb42adb9f79b6c1fflorian assert(clientname != NULL); 97b593be39d80165efa84ee5f1fb42adb9f79b6c1fflorian 98b593be39d80165efa84ee5f1fb42adb9f79b6c1fflorian if (path == NULL) return clientname; 99b593be39d80165efa84ee5f1fb42adb9f79b6c1fflorian 1001ae53537439204ae45e6b00ea788fc8fbc06f859florian /* Make the size of the FULLNAME buffer large enough. */ 1011ae53537439204ae45e6b00ea788fc8fbc06f859florian unsigned need = strlen(path) + strlen("/") + strlen(clientname) + 1; 1021ae53537439204ae45e6b00ea788fc8fbc06f859florian 1031ae53537439204ae45e6b00ea788fc8fbc06f859florian fullname = malloc(need); 1041ae53537439204ae45e6b00ea788fc8fbc06f859florian if (fullname == NULL) 1051ae53537439204ae45e6b00ea788fc8fbc06f859florian barf("malloc of fullname failed."); 1061ae53537439204ae45e6b00ea788fc8fbc06f859florian 107fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom while (path) 108fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom { 109fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom if ((colon = strchr(path, ':')) == NULL) 110fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom { 111fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom strcpy(fullname, path); 112fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom path = NULL; 113fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom } 114fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom else 115fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom { 1161ae53537439204ae45e6b00ea788fc8fbc06f859florian strncpy(fullname, path, colon - path); 117fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom fullname[colon - path] = '\0'; 118fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom path = colon + 1; 119fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom } 120fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom 121fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom strcat(fullname, "/"); 122fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom strcat(fullname, clientname); 123fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom 124fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom if (access(fullname, R_OK|X_OK) == 0) 125fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom return fullname; 126fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom } 127b593be39d80165efa84ee5f1fb42adb9f79b6c1fflorian free(fullname); 128fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom 129fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom return clientname; 130fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom} 131fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom 132fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom/* Examine the client and work out which platform it is for */ 133fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtomstatic const char *select_platform(const char *clientname) 134fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom{ 135fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom int fd; 13619f91bbaedb4caef8a60ce94b0f507193cc0bc10florian char header[4096]; 13758899e8e2af51859289d0badea881b7b72c3fb13njn ssize_t n_bytes; 138fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom const char *platform = NULL; 139fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom 1401edc55a25a2f28cdc0cc72e3e18f5cc0c4eb927etom VG_(debugLog)(2, "launcher", "selecting platform for '%s'\n", clientname); 1411edc55a25a2f28cdc0cc72e3e18f5cc0c4eb927etom 142fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom if (strchr(clientname, '/') == NULL) 143fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom clientname = find_client(clientname); 144fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom 1451edc55a25a2f28cdc0cc72e3e18f5cc0c4eb927etom VG_(debugLog)(2, "launcher", "selecting platform for '%s'\n", clientname); 1461edc55a25a2f28cdc0cc72e3e18f5cc0c4eb927etom 147fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom if ((fd = open(clientname, O_RDONLY)) < 0) 148fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom return NULL; 149fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom // barf("open(%s): %s", clientname, strerror(errno)); 150fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom 1511edc55a25a2f28cdc0cc72e3e18f5cc0c4eb927etom VG_(debugLog)(2, "launcher", "opened '%s'\n", clientname); 1521edc55a25a2f28cdc0cc72e3e18f5cc0c4eb927etom 15358899e8e2af51859289d0badea881b7b72c3fb13njn n_bytes = read(fd, header, sizeof(header)); 154fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom close(fd); 15558899e8e2af51859289d0badea881b7b72c3fb13njn if (n_bytes < 2) { 15633e57a7bcf079398e9003f892a853037f9bd5de0njn return NULL; 15733e57a7bcf079398e9003f892a853037f9bd5de0njn } 158fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom 1596431e308474c88cd5da785b639816cc4321db4c7sewardj VG_(debugLog)(2, "launcher", "read %ld bytes from '%s'\n", 1606431e308474c88cd5da785b639816cc4321db4c7sewardj (long int)n_bytes, clientname); 1611edc55a25a2f28cdc0cc72e3e18f5cc0c4eb927etom 162fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom if (header[0] == '#' && header[1] == '!') { 16358899e8e2af51859289d0badea881b7b72c3fb13njn int i = 2; 164fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom 165695dde81fe9ba126d9a1a57cb38dcccf95426e3eflorian STATIC_ASSERT(VKI_BINPRM_BUF_SIZE < sizeof header); 166695dde81fe9ba126d9a1a57cb38dcccf95426e3eflorian if (n_bytes > VKI_BINPRM_BUF_SIZE) 167695dde81fe9ba126d9a1a57cb38dcccf95426e3eflorian n_bytes = VKI_BINPRM_BUF_SIZE - 1; 168695dde81fe9ba126d9a1a57cb38dcccf95426e3eflorian header[n_bytes] = '\0'; 169695dde81fe9ba126d9a1a57cb38dcccf95426e3eflorian char *eol = strchr(header, '\n'); 170695dde81fe9ba126d9a1a57cb38dcccf95426e3eflorian if (eol != NULL) 171695dde81fe9ba126d9a1a57cb38dcccf95426e3eflorian *eol = '\0'; 172695dde81fe9ba126d9a1a57cb38dcccf95426e3eflorian 17358899e8e2af51859289d0badea881b7b72c3fb13njn // Skip whitespace. 174695dde81fe9ba126d9a1a57cb38dcccf95426e3eflorian while (header[i] == ' '|| header[i] == '\t') 17558899e8e2af51859289d0badea881b7b72c3fb13njn i++; 176fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom 17758899e8e2af51859289d0badea881b7b72c3fb13njn // Get the interpreter name. 178695dde81fe9ba126d9a1a57cb38dcccf95426e3eflorian const char *interp = header + i; 179695dde81fe9ba126d9a1a57cb38dcccf95426e3eflorian 180695dde81fe9ba126d9a1a57cb38dcccf95426e3eflorian if (header[i] == '\0') { 181695dde81fe9ba126d9a1a57cb38dcccf95426e3eflorian // No interpreter was found; fall back to default shell 182695dde81fe9ba126d9a1a57cb38dcccf95426e3eflorian# if defined(VGPV_arm_linux_android) \ 183695dde81fe9ba126d9a1a57cb38dcccf95426e3eflorian || defined(VGPV_x86_linux_android) \ 184695dde81fe9ba126d9a1a57cb38dcccf95426e3eflorian || defined(VGPV_mips32_linux_android) \ 185695dde81fe9ba126d9a1a57cb38dcccf95426e3eflorian || defined(VGPV_arm64_linux_android) 186695dde81fe9ba126d9a1a57cb38dcccf95426e3eflorian interp = "/system/bin/sh"; 187695dde81fe9ba126d9a1a57cb38dcccf95426e3eflorian# else 188695dde81fe9ba126d9a1a57cb38dcccf95426e3eflorian interp = "/bin/sh"; 189695dde81fe9ba126d9a1a57cb38dcccf95426e3eflorian# endif 190695dde81fe9ba126d9a1a57cb38dcccf95426e3eflorian } else { 191695dde81fe9ba126d9a1a57cb38dcccf95426e3eflorian while (header[i]) { 192695dde81fe9ba126d9a1a57cb38dcccf95426e3eflorian if (header[i] == ' ' || header[i] == '\t') break; 193695dde81fe9ba126d9a1a57cb38dcccf95426e3eflorian i++; 194695dde81fe9ba126d9a1a57cb38dcccf95426e3eflorian } 195695dde81fe9ba126d9a1a57cb38dcccf95426e3eflorian header[i] = '\0'; 19658899e8e2af51859289d0badea881b7b72c3fb13njn } 197fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom 198fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom platform = select_platform(interp); 1992108204443f84bfa733397be519bdcf6810c5127cerion 20058899e8e2af51859289d0badea881b7b72c3fb13njn } else if (n_bytes >= SELFMAG && memcmp(header, ELFMAG, SELFMAG) == 0) { 20158899e8e2af51859289d0badea881b7b72c3fb13njn 20258899e8e2af51859289d0badea881b7b72c3fb13njn if (n_bytes >= sizeof(Elf32_Ehdr) && header[EI_CLASS] == ELFCLASS32) { 2032108204443f84bfa733397be519bdcf6810c5127cerion const Elf32_Ehdr *ehdr = (Elf32_Ehdr *)header; 2042108204443f84bfa733397be519bdcf6810c5127cerion 2052108204443f84bfa733397be519bdcf6810c5127cerion if (header[EI_DATA] == ELFDATA2LSB) { 2062108204443f84bfa733397be519bdcf6810c5127cerion if (ehdr->e_machine == EM_386 && 2074ff8f6cd403fa8be4a39b576dd1273ae96500d2atom (ehdr->e_ident[EI_OSABI] == ELFOSABI_SYSV || 2084ff8f6cd403fa8be4a39b576dd1273ae96500d2atom ehdr->e_ident[EI_OSABI] == ELFOSABI_LINUX)) { 2092108204443f84bfa733397be519bdcf6810c5127cerion platform = "x86-linux"; 2102108204443f84bfa733397be519bdcf6810c5127cerion } 21159570ffbe31930ab4d678754daaeec0715117a3dsewardj else 21259570ffbe31930ab4d678754daaeec0715117a3dsewardj if (ehdr->e_machine == EM_ARM && 21359570ffbe31930ab4d678754daaeec0715117a3dsewardj (ehdr->e_ident[EI_OSABI] == ELFOSABI_SYSV || 21459570ffbe31930ab4d678754daaeec0715117a3dsewardj ehdr->e_ident[EI_OSABI] == ELFOSABI_LINUX)) { 21559570ffbe31930ab4d678754daaeec0715117a3dsewardj platform = "arm-linux"; 21659570ffbe31930ab4d678754daaeec0715117a3dsewardj } 2175db15403e889d4db339b342bc2a824ef0bfaa654sewardj else 2185db15403e889d4db339b342bc2a824ef0bfaa654sewardj if (ehdr->e_machine == EM_MIPS && 2195db15403e889d4db339b342bc2a824ef0bfaa654sewardj (ehdr->e_ident[EI_OSABI] == ELFOSABI_SYSV || 2205db15403e889d4db339b342bc2a824ef0bfaa654sewardj ehdr->e_ident[EI_OSABI] == ELFOSABI_LINUX)) { 2215db15403e889d4db339b342bc2a824ef0bfaa654sewardj platform = "mips32-linux"; 2225db15403e889d4db339b342bc2a824ef0bfaa654sewardj } 2232108204443f84bfa733397be519bdcf6810c5127cerion } 2242108204443f84bfa733397be519bdcf6810c5127cerion else if (header[EI_DATA] == ELFDATA2MSB) { 2252108204443f84bfa733397be519bdcf6810c5127cerion if (ehdr->e_machine == EM_PPC && 2264ff8f6cd403fa8be4a39b576dd1273ae96500d2atom (ehdr->e_ident[EI_OSABI] == ELFOSABI_SYSV || 2274ff8f6cd403fa8be4a39b576dd1273ae96500d2atom ehdr->e_ident[EI_OSABI] == ELFOSABI_LINUX)) { 2282108204443f84bfa733397be519bdcf6810c5127cerion platform = "ppc32-linux"; 2292108204443f84bfa733397be519bdcf6810c5127cerion } 2305db15403e889d4db339b342bc2a824ef0bfaa654sewardj else 2315db15403e889d4db339b342bc2a824ef0bfaa654sewardj if (ehdr->e_machine == EM_MIPS && 2325db15403e889d4db339b342bc2a824ef0bfaa654sewardj (ehdr->e_ident[EI_OSABI] == ELFOSABI_SYSV || 2335db15403e889d4db339b342bc2a824ef0bfaa654sewardj ehdr->e_ident[EI_OSABI] == ELFOSABI_LINUX)) { 2345db15403e889d4db339b342bc2a824ef0bfaa654sewardj platform = "mips32-linux"; 2355db15403e889d4db339b342bc2a824ef0bfaa654sewardj } 2362108204443f84bfa733397be519bdcf6810c5127cerion } 23759570ffbe31930ab4d678754daaeec0715117a3dsewardj 23858899e8e2af51859289d0badea881b7b72c3fb13njn } else if (n_bytes >= sizeof(Elf64_Ehdr) && header[EI_CLASS] == ELFCLASS64) { 2392108204443f84bfa733397be519bdcf6810c5127cerion const Elf64_Ehdr *ehdr = (Elf64_Ehdr *)header; 2402108204443f84bfa733397be519bdcf6810c5127cerion 2412108204443f84bfa733397be519bdcf6810c5127cerion if (header[EI_DATA] == ELFDATA2LSB) { 2422108204443f84bfa733397be519bdcf6810c5127cerion if (ehdr->e_machine == EM_X86_64 && 2434ff8f6cd403fa8be4a39b576dd1273ae96500d2atom (ehdr->e_ident[EI_OSABI] == ELFOSABI_SYSV || 2444ff8f6cd403fa8be4a39b576dd1273ae96500d2atom ehdr->e_ident[EI_OSABI] == ELFOSABI_LINUX)) { 2452108204443f84bfa733397be519bdcf6810c5127cerion platform = "amd64-linux"; 2464df0bfc0614379192c780c944415dc420d9cfe8epetarj } else if (ehdr->e_machine == EM_MIPS && 2474df0bfc0614379192c780c944415dc420d9cfe8epetarj (ehdr->e_ident[EI_OSABI] == ELFOSABI_SYSV || 2484df0bfc0614379192c780c944415dc420d9cfe8epetarj ehdr->e_ident[EI_OSABI] == ELFOSABI_LINUX)) { 2494df0bfc0614379192c780c944415dc420d9cfe8epetarj platform = "mips64-linux"; 250112711afefcfcd43680c7c4aa8d38ef180e8811esewardj } else if (ehdr->e_machine == EM_TILEGX && 251112711afefcfcd43680c7c4aa8d38ef180e8811esewardj (ehdr->e_ident[EI_OSABI] == ELFOSABI_SYSV || 252112711afefcfcd43680c7c4aa8d38ef180e8811esewardj ehdr->e_ident[EI_OSABI] == ELFOSABI_LINUX)) { 253112711afefcfcd43680c7c4aa8d38ef180e8811esewardj platform = "tilegx-linux"; 254f0c1250e324f6684757c6a15545366447ef1d64fsewardj } else if (ehdr->e_machine == EM_AARCH64 && 255f0c1250e324f6684757c6a15545366447ef1d64fsewardj (ehdr->e_ident[EI_OSABI] == ELFOSABI_SYSV || 256f0c1250e324f6684757c6a15545366447ef1d64fsewardj ehdr->e_ident[EI_OSABI] == ELFOSABI_LINUX)) { 257f0c1250e324f6684757c6a15545366447ef1d64fsewardj platform = "arm64-linux"; 258582d58245637ab05272d89fb94b12fd0f18fa0f8carll } else if (ehdr->e_machine == EM_PPC64 && 259582d58245637ab05272d89fb94b12fd0f18fa0f8carll (ehdr->e_ident[EI_OSABI] == ELFOSABI_SYSV || 260582d58245637ab05272d89fb94b12fd0f18fa0f8carll ehdr->e_ident[EI_OSABI] == ELFOSABI_LINUX)) { 261582d58245637ab05272d89fb94b12fd0f18fa0f8carll platform = "ppc64le-linux"; 2622108204443f84bfa733397be519bdcf6810c5127cerion } 2632108204443f84bfa733397be519bdcf6810c5127cerion } else if (header[EI_DATA] == ELFDATA2MSB) { 2649c6b05db45362b1afb981aa8298ab12ab4027b1adejanj# if !defined(VGPV_arm_linux_android) \ 2659c6b05db45362b1afb981aa8298ab12ab4027b1adejanj && !defined(VGPV_x86_linux_android) \ 26626ed419d60369d0545510eba0832566e24452e1esewardj && !defined(VGPV_mips32_linux_android) \ 26726ed419d60369d0545510eba0832566e24452e1esewardj && !defined(VGPV_arm64_linux_android) 2682108204443f84bfa733397be519bdcf6810c5127cerion if (ehdr->e_machine == EM_PPC64 && 2694ff8f6cd403fa8be4a39b576dd1273ae96500d2atom (ehdr->e_ident[EI_OSABI] == ELFOSABI_SYSV || 2704ff8f6cd403fa8be4a39b576dd1273ae96500d2atom ehdr->e_ident[EI_OSABI] == ELFOSABI_LINUX)) { 271cae0cc22b83ffb260ee8379e92099c5a701944cbcarll platform = "ppc64be-linux"; 272ca8d94ac2e864f3034f39c2e45d78a32cfcdb2bbsewardj } 273ca8d94ac2e864f3034f39c2e45d78a32cfcdb2bbsewardj else 274ca8d94ac2e864f3034f39c2e45d78a32cfcdb2bbsewardj if (ehdr->e_machine == EM_S390 && 275ca8d94ac2e864f3034f39c2e45d78a32cfcdb2bbsewardj (ehdr->e_ident[EI_OSABI] == ELFOSABI_SYSV || 276ca8d94ac2e864f3034f39c2e45d78a32cfcdb2bbsewardj ehdr->e_ident[EI_OSABI] == ELFOSABI_LINUX)) { 277b5b87408c0c99f9f6938d8cd921e2a5f420577c4sewardj platform = "s390x-linux"; 2784df0bfc0614379192c780c944415dc420d9cfe8epetarj } else if (ehdr->e_machine == EM_MIPS && 2794df0bfc0614379192c780c944415dc420d9cfe8epetarj (ehdr->e_ident[EI_OSABI] == ELFOSABI_SYSV || 2804df0bfc0614379192c780c944415dc420d9cfe8epetarj ehdr->e_ident[EI_OSABI] == ELFOSABI_LINUX)) { 2814df0bfc0614379192c780c944415dc420d9cfe8epetarj platform = "mips64-linux"; 2822108204443f84bfa733397be519bdcf6810c5127cerion } 283ca8d94ac2e864f3034f39c2e45d78a32cfcdb2bbsewardj# endif 2842108204443f84bfa733397be519bdcf6810c5127cerion } 285fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom } 286fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom } 287fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom 2881edc55a25a2f28cdc0cc72e3e18f5cc0c4eb927etom VG_(debugLog)(2, "launcher", "selected platform '%s'\n", 2891edc55a25a2f28cdc0cc72e3e18f5cc0c4eb927etom platform ? platform : "unknown"); 2901edc55a25a2f28cdc0cc72e3e18f5cc0c4eb927etom 291fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom return platform; 292fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom} 293fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom 29445f4e7c91119c7d01a59f5e827c67841632c9314sewardj/* Where we expect to find all our aux files */ 29545f4e7c91119c7d01a59f5e827c67841632c9314sewardjstatic const char *valgrind_lib = VG_LIBDIR; 29645f4e7c91119c7d01a59f5e827c67841632c9314sewardj 29745f4e7c91119c7d01a59f5e827c67841632c9314sewardjint main(int argc, char** argv, char** envp) 29845f4e7c91119c7d01a59f5e827c67841632c9314sewardj{ 29945f4e7c91119c7d01a59f5e827c67841632c9314sewardj int i, j, loglevel, r; 30045f4e7c91119c7d01a59f5e827c67841632c9314sewardj const char *toolname = NULL; 301fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom const char *clientname = NULL; 302fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom const char *platform; 3038813eef4f290add8e7d66db4deae8cedddcb68bcsewardj const char *default_platform; 30445f4e7c91119c7d01a59f5e827c67841632c9314sewardj const char *cp; 30545f4e7c91119c7d01a59f5e827c67841632c9314sewardj char *toolfile; 3060c89e9b0812fb26324a5c5a392bbce01ae92582dflorian const char *launcher_name; 30745f4e7c91119c7d01a59f5e827c67841632c9314sewardj char* new_line; 30845f4e7c91119c7d01a59f5e827c67841632c9314sewardj char** new_env; 30945f4e7c91119c7d01a59f5e827c67841632c9314sewardj 31045f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* Start the debugging-log system ASAP. First find out how many 31145f4e7c91119c7d01a59f5e827c67841632c9314sewardj "-d"s were specified. This is a pre-scan of the command line. 31245f4e7c91119c7d01a59f5e827c67841632c9314sewardj At the same time, look for the tool name. */ 31345f4e7c91119c7d01a59f5e827c67841632c9314sewardj loglevel = 0; 31445f4e7c91119c7d01a59f5e827c67841632c9314sewardj for (i = 1; i < argc; i++) { 315fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom if (argv[i][0] != '-') { 316fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom clientname = argv[i]; 31745f4e7c91119c7d01a59f5e827c67841632c9314sewardj break; 318fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom } 319fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom if (0 == strcmp(argv[i], "--")) { 320fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom if (i+1 < argc) 321fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom clientname = argv[i+1]; 32245f4e7c91119c7d01a59f5e827c67841632c9314sewardj break; 323fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom } 32445f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (0 == strcmp(argv[i], "-d")) 32545f4e7c91119c7d01a59f5e827c67841632c9314sewardj loglevel++; 32645f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (0 == strncmp(argv[i], "--tool=", 7)) 32745f4e7c91119c7d01a59f5e827c67841632c9314sewardj toolname = argv[i] + 7; 32845f4e7c91119c7d01a59f5e827c67841632c9314sewardj } 32945f4e7c91119c7d01a59f5e827c67841632c9314sewardj 33045f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* ... and start the debug logger. Now we can safely emit logging 33145f4e7c91119c7d01a59f5e827c67841632c9314sewardj messages all through startup. */ 33245f4e7c91119c7d01a59f5e827c67841632c9314sewardj VG_(debugLog_startup)(loglevel, "Stage 1"); 33345f4e7c91119c7d01a59f5e827c67841632c9314sewardj 33445f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* Make sure we know which tool we're using */ 33545f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (toolname) { 33645f4e7c91119c7d01a59f5e827c67841632c9314sewardj VG_(debugLog)(1, "launcher", "tool '%s' requested\n", toolname); 33745f4e7c91119c7d01a59f5e827c67841632c9314sewardj } else { 33845f4e7c91119c7d01a59f5e827c67841632c9314sewardj VG_(debugLog)(1, "launcher", 33945f4e7c91119c7d01a59f5e827c67841632c9314sewardj "no tool requested, defaulting to 'memcheck'\n"); 34045f4e7c91119c7d01a59f5e827c67841632c9314sewardj toolname = "memcheck"; 34145f4e7c91119c7d01a59f5e827c67841632c9314sewardj } 34245f4e7c91119c7d01a59f5e827c67841632c9314sewardj 3438813eef4f290add8e7d66db4deae8cedddcb68bcsewardj /* Select a platform to use if we can't decide that by looking at 344e8ffbc22ce035642f85f59f27fb87152805e641eflorian the executable (eg because it's a shell script). VG_PLATFORM is the 345e8ffbc22ce035642f85f59f27fb87152805e641eflorian default_platform. Its value is defined in coregrind/Makefile.am and 346e8ffbc22ce035642f85f59f27fb87152805e641eflorian typically it is the primary build target. Unless the primary build 347e8ffbc22ce035642f85f59f27fb87152805e641eflorian target is not built is not built in which case VG_PLATFORM is the 348e8ffbc22ce035642f85f59f27fb87152805e641eflorian secondary build target. */ 349f0c1250e324f6684757c6a15545366447ef1d64fsewardj if ((0==strcmp(VG_PLATFORM,"x86-linux")) || 350f0c1250e324f6684757c6a15545366447ef1d64fsewardj (0==strcmp(VG_PLATFORM,"amd64-linux")) || 351f0c1250e324f6684757c6a15545366447ef1d64fsewardj (0==strcmp(VG_PLATFORM,"ppc32-linux")) || 352cae0cc22b83ffb260ee8379e92099c5a701944cbcarll (0==strcmp(VG_PLATFORM,"ppc64be-linux")) || 353582d58245637ab05272d89fb94b12fd0f18fa0f8carll (0==strcmp(VG_PLATFORM,"ppc64le-linux")) || 354f0c1250e324f6684757c6a15545366447ef1d64fsewardj (0==strcmp(VG_PLATFORM,"arm-linux")) || 355f0c1250e324f6684757c6a15545366447ef1d64fsewardj (0==strcmp(VG_PLATFORM,"arm64-linux")) || 356f0c1250e324f6684757c6a15545366447ef1d64fsewardj (0==strcmp(VG_PLATFORM,"s390x-linux")) || 357112711afefcfcd43680c7c4aa8d38ef180e8811esewardj (0==strcmp(VG_PLATFORM,"tilegx-linux")) || 3584df0bfc0614379192c780c944415dc420d9cfe8epetarj (0==strcmp(VG_PLATFORM,"mips32-linux")) || 3594df0bfc0614379192c780c944415dc420d9cfe8epetarj (0==strcmp(VG_PLATFORM,"mips64-linux"))) 3604f350d1b47ccaa7a579b52cafa6f75ffe04f415cnjn default_platform = VG_PLATFORM; 3618813eef4f290add8e7d66db4deae8cedddcb68bcsewardj else 3628813eef4f290add8e7d66db4deae8cedddcb68bcsewardj barf("Unknown VG_PLATFORM '%s'", VG_PLATFORM); 3638813eef4f290add8e7d66db4deae8cedddcb68bcsewardj 3648813eef4f290add8e7d66db4deae8cedddcb68bcsewardj /* Work out what platform to use, or use the default platform if 3658813eef4f290add8e7d66db4deae8cedddcb68bcsewardj not possible. */ 366fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom if (clientname == NULL) { 3678813eef4f290add8e7d66db4deae8cedddcb68bcsewardj VG_(debugLog)(1, "launcher", 3688813eef4f290add8e7d66db4deae8cedddcb68bcsewardj "no client specified, defaulting platform to '%s'\n", 3698813eef4f290add8e7d66db4deae8cedddcb68bcsewardj default_platform); 3708813eef4f290add8e7d66db4deae8cedddcb68bcsewardj platform = default_platform; 371fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom } else if ((platform = select_platform(clientname)) != NULL) { 372fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom VG_(debugLog)(1, "launcher", "selected platform '%s'\n", platform); 373fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom } else { 3748813eef4f290add8e7d66db4deae8cedddcb68bcsewardj VG_(debugLog)(1, "launcher", 3758813eef4f290add8e7d66db4deae8cedddcb68bcsewardj "no platform detected, defaulting platform to '%s'\n", 3768813eef4f290add8e7d66db4deae8cedddcb68bcsewardj default_platform); 3778813eef4f290add8e7d66db4deae8cedddcb68bcsewardj platform = default_platform; 378fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom } 379fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom 38045f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* Figure out the name of this executable (viz, the launcher), so 38145f4e7c91119c7d01a59f5e827c67841632c9314sewardj we can tell stage2. stage2 will use the name for recursive 38258899e8e2af51859289d0badea881b7b72c3fb13njn invocations of valgrind on child processes. */ 3830c89e9b0812fb26324a5c5a392bbce01ae92582dflorian unsigned bufsiz = 0; 3840c89e9b0812fb26324a5c5a392bbce01ae92582dflorian char *buf = NULL; 3850c89e9b0812fb26324a5c5a392bbce01ae92582dflorian 3860c89e9b0812fb26324a5c5a392bbce01ae92582dflorian while (42) { 3870c89e9b0812fb26324a5c5a392bbce01ae92582dflorian bufsiz += 500; 3880c89e9b0812fb26324a5c5a392bbce01ae92582dflorian buf = realloc(buf, bufsiz); 3890c89e9b0812fb26324a5c5a392bbce01ae92582dflorian if (buf == NULL) 3900c89e9b0812fb26324a5c5a392bbce01ae92582dflorian barf("realloc of buf failed."); 3910c89e9b0812fb26324a5c5a392bbce01ae92582dflorian r = readlink("/proc/self/exe", buf, bufsiz); 3920c89e9b0812fb26324a5c5a392bbce01ae92582dflorian if (r == -1) { 3930c89e9b0812fb26324a5c5a392bbce01ae92582dflorian /* If /proc/self/exe can't be followed, don't give up. Instead 3940c89e9b0812fb26324a5c5a392bbce01ae92582dflorian continue with an empty string for VALGRIND_LAUNCHER. In the 3950c89e9b0812fb26324a5c5a392bbce01ae92582dflorian sys_execve wrapper, this is tested, and if found to be empty, 3960c89e9b0812fb26324a5c5a392bbce01ae92582dflorian fail the execve. */ 3970c89e9b0812fb26324a5c5a392bbce01ae92582dflorian fprintf(stderr, "valgrind: warning (non-fatal): " 3980c89e9b0812fb26324a5c5a392bbce01ae92582dflorian "readlink(\"/proc/self/exe\") failed.\n"); 3990c89e9b0812fb26324a5c5a392bbce01ae92582dflorian fprintf(stderr, "valgrind: continuing, however --trace-children=yes " 4000c89e9b0812fb26324a5c5a392bbce01ae92582dflorian "will not work.\n"); 4010c89e9b0812fb26324a5c5a392bbce01ae92582dflorian launcher_name = ""; 4020c89e9b0812fb26324a5c5a392bbce01ae92582dflorian break; 4030c89e9b0812fb26324a5c5a392bbce01ae92582dflorian } 4040c89e9b0812fb26324a5c5a392bbce01ae92582dflorian if (r == bufsiz) continue; // buffer to small; retry 4050c89e9b0812fb26324a5c5a392bbce01ae92582dflorian 4060c89e9b0812fb26324a5c5a392bbce01ae92582dflorian assert(r < bufsiz); // paranoia 4070c89e9b0812fb26324a5c5a392bbce01ae92582dflorian 4080c89e9b0812fb26324a5c5a392bbce01ae92582dflorian buf[r] = '\0'; 4090c89e9b0812fb26324a5c5a392bbce01ae92582dflorian launcher_name = buf; 4100c89e9b0812fb26324a5c5a392bbce01ae92582dflorian break; 41198e68a4db8df087243c5f095cddb7b34adb2d19bsewardj } 41245f4e7c91119c7d01a59f5e827c67841632c9314sewardj 41345f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* tediously augment the env: VALGRIND_LAUNCHER=launcher_name */ 41445f4e7c91119c7d01a59f5e827c67841632c9314sewardj new_line = malloc(strlen(VALGRIND_LAUNCHER) + 1 41545f4e7c91119c7d01a59f5e827c67841632c9314sewardj + strlen(launcher_name) + 1); 41645f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (new_line == NULL) 41745f4e7c91119c7d01a59f5e827c67841632c9314sewardj barf("malloc of new_line failed."); 41845f4e7c91119c7d01a59f5e827c67841632c9314sewardj strcpy(new_line, VALGRIND_LAUNCHER); 41945f4e7c91119c7d01a59f5e827c67841632c9314sewardj strcat(new_line, "="); 42045f4e7c91119c7d01a59f5e827c67841632c9314sewardj strcat(new_line, launcher_name); 42145f4e7c91119c7d01a59f5e827c67841632c9314sewardj 42245f4e7c91119c7d01a59f5e827c67841632c9314sewardj for (j = 0; envp[j]; j++) 42345f4e7c91119c7d01a59f5e827c67841632c9314sewardj ; 42445f4e7c91119c7d01a59f5e827c67841632c9314sewardj new_env = malloc((j+2) * sizeof(char*)); 42545f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (new_env == NULL) 42645f4e7c91119c7d01a59f5e827c67841632c9314sewardj barf("malloc of new_env failed."); 42745f4e7c91119c7d01a59f5e827c67841632c9314sewardj for (i = 0; i < j; i++) 42845f4e7c91119c7d01a59f5e827c67841632c9314sewardj new_env[i] = envp[i]; 42945f4e7c91119c7d01a59f5e827c67841632c9314sewardj new_env[i++] = new_line; 43045f4e7c91119c7d01a59f5e827c67841632c9314sewardj new_env[i++] = NULL; 43145f4e7c91119c7d01a59f5e827c67841632c9314sewardj assert(i == j+2); 43245f4e7c91119c7d01a59f5e827c67841632c9314sewardj 43345f4e7c91119c7d01a59f5e827c67841632c9314sewardj /* Establish the correct VALGRIND_LIB. */ 43445f4e7c91119c7d01a59f5e827c67841632c9314sewardj cp = getenv(VALGRIND_LIB); 43545f4e7c91119c7d01a59f5e827c67841632c9314sewardj 43645f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (cp != NULL) 43745f4e7c91119c7d01a59f5e827c67841632c9314sewardj valgrind_lib = cp; 43845f4e7c91119c7d01a59f5e827c67841632c9314sewardj 43958899e8e2af51859289d0badea881b7b72c3fb13njn /* Build the stage2 invocation, and execve it. Bye! */ 440fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom toolfile = malloc(strlen(valgrind_lib) + strlen(toolname) + strlen(platform) + 3); 44145f4e7c91119c7d01a59f5e827c67841632c9314sewardj if (toolfile == NULL) 44245f4e7c91119c7d01a59f5e827c67841632c9314sewardj barf("malloc of toolfile failed."); 4436bf365c2d4e55cb109d20e0a8f90dc121bdc003fnjn sprintf(toolfile, "%s/%s-%s", valgrind_lib, toolname, platform); 44445f4e7c91119c7d01a59f5e827c67841632c9314sewardj 44545f4e7c91119c7d01a59f5e827c67841632c9314sewardj VG_(debugLog)(1, "launcher", "launching %s\n", toolfile); 44645f4e7c91119c7d01a59f5e827c67841632c9314sewardj 44745f4e7c91119c7d01a59f5e827c67841632c9314sewardj execve(toolfile, argv, new_env); 44845f4e7c91119c7d01a59f5e827c67841632c9314sewardj 449fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom fprintf(stderr, "valgrind: failed to start tool '%s' for platform '%s': %s\n", 450fb7bcde4e3d8afdcd267b4da904f777cfd8ed1bbtom toolname, platform, strerror(errno)); 45145f4e7c91119c7d01a59f5e827c67841632c9314sewardj 45245f4e7c91119c7d01a59f5e827c67841632c9314sewardj exit(1); 45345f4e7c91119c7d01a59f5e827c67841632c9314sewardj} 454