1/* Copyright (C) 2021 Free Software Foundation, Inc. 2 Contributed by Oracle. 3 4 This file is part of GNU Binutils. 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3, or (at your option) 9 any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software 18 Foundation, 51 Franklin Street - Fifth Floor, Boston, 19 MA 02110-1301, USA. */ 20 21#include "config.h" 22#include <ctype.h> 23#include <stdio.h> 24#include <stdlib.h> 25#include <unistd.h> 26#include <strings.h> 27#include <string.h> 28#include <sys/types.h> 29#include <sys/stat.h> 30#include <errno.h> 31#include <i18n.h> 32#include <Elf.h> 33#include <collctrl.h> 34#include <StringBuilder.h> 35#include "collect.h" 36 37/* get_count_data -- format exec of bit to do the real work */ 38void 39collect::get_count_data () 40{ 41 char command[8192]; 42 char *s; 43 struct stat statbuf; 44 45 // reserve space for original args, plus 30 arguments to bit 46 nargs = origargc + 30; 47 char **narglist = (char **) calloc (nargs, sizeof (char *)); 48 arglist = narglist; 49 50 // construct the command for bit 51 snprintf (command, sizeof (command), NTXT ("%s"), run_dir); 52 s = strstr_r (command, NTXT ("/bin")); 53 if (s != NULL) 54 { 55 // build command line for launching it 56 snprintf (s, sizeof (command) - (s - command), NTXT ("/lib/compilers/bit")); 57 if (stat (command, &statbuf) == -1) 58 { 59 // if bit command does not exist there 60 char *first_look = strdup (command); 61 snprintf (command, sizeof (command), NTXT ("%s"), run_dir); 62 s = strstr (command, NTXT ("/bin")); 63 snprintf (s, sizeof (command) - (s - command), NTXT ("/prod/bin/bit")); 64 if (stat (command, &statbuf) == -1) 65 { 66 // if bit command does not exist 67 dbe_write (2, GTXT ("bit is not installed as `%s' or `%s'\nNo experiment is possible\n"), first_look, command); 68 exit (2); 69 } 70 free (first_look); 71 } 72 *arglist++ = strdup (command); 73 } 74 else 75 { 76 dbe_write (2, GTXT ("collect can't find install bin directory\n")); 77 exit (1); 78 } 79 80 // Tell it to collect data 81 *arglist++ = NTXT ("collect"); 82 83 // add the flag for real-data vs. static data 84 switch (cc->get_count ()) 85 { 86 case -1: 87 *arglist++ = NTXT ("-i"); 88 *arglist++ = NTXT ("static"); 89 *arglist++ = NTXT ("-M"); 90 break; 91 case 1: 92 *arglist++ = NTXT ("-M"); 93 *arglist++ = NTXT ("-u"); 94 break; 95 default: 96 abort (); 97 } 98 99 // tell bit to produce an experiment 100 *arglist++ = NTXT ("-e"); 101 102 // now copy an edited list of collect options to the arglist 103 char **oargv = origargv; 104 105 // skip the "collect" 106 oargv++; 107 int argc = 1; 108 while (argc != targ_index) 109 { 110 char *p = *oargv; 111 switch (p[1]) 112 { 113 // pass these arguments along, with parameter 114 case 'o': 115 case 'd': 116 case 'g': 117 case 'A': 118 case 'C': 119 case 'O': 120 case 'N': 121 *arglist++ = *oargv++; 122 *arglist++ = *oargv++; 123 argc = argc + 2; 124 break; 125 case 'I': 126 *arglist++ = *oargv++; // set the -I flag 127 *arglist++ = *oargv; // and the directory name 128 *arglist++ = NTXT ("-d"); // and the -d flag 129 *arglist++ = *oargv++; // to the same directory name 130 argc = argc + 2; 131 break; 132 case 'n': 133 case 'v': 134 // pass these arguments along as is 135 *arglist++ = *oargv++; 136 argc = argc + 1; 137 break; 138 case 'x': 139 // skip one argument 140 oargv++; 141 argc++; 142 break; 143 case 'c': 144 case 'L': 145 case 'y': 146 case 'l': 147 case 'F': 148 case 'j': 149 case 'J': 150 case 'p': 151 case 's': 152 case 'h': 153 case 'S': 154 case 'm': 155 case 'M': 156 case 'H': 157 case 'r': 158 case 'i': 159 // skip two arguments 160 oargv++; 161 oargv++; 162 argc = argc + 2; 163 break; 164 case 'R': 165 case 'Z': 166 default: 167 // these should never get this far 168 dbe_write (2, GTXT ("unexpected argument %s\n"), p); 169 abort (); 170 } 171 } 172 173 // now copy the target and its arguments 174 if (access (prog_name, X_OK) != 0) // not found 175 *arglist++ = *oargv++; 176 else 177 { 178 oargv++; 179 *arglist++ = prog_name; 180 } 181 while (*oargv != NULL) 182 *arglist++ = *oargv++; 183 184 /* now we have the full argument list composed; if verbose, print it */ 185 if ((verbose == 1) || (disabled)) 186 { 187 /* describe the experiment */ 188 char *ccret = cc->show (0); 189 if (ccret != NULL) 190 { 191 writeStr (2, ccret); 192 free (ccret); 193 } 194 ccret = cc->show_expt (); 195 if (ccret != NULL) 196 { 197 /* write this to stdout */ 198 writeStr (1, ccret); 199 free (ccret); 200 } 201 /* print the arguments to bit */ 202 arglist = narglist; 203 StringBuilder sb; 204 sb.append (NTXT ("Exec argv[] = ")); 205 for (int ret = 0; ret < nargs; ret++) 206 { 207 if (narglist[ret] == NULL) 208 break; 209 if (ret > 0) 210 sb.append (NTXT (" ")); 211 sb.append (narglist[ret]); 212 } 213 sb.append (NTXT ("\n\n")); 214 write (2, sb.toString (), sb.length ()); 215 } 216 217 /* check for dry run */ 218 if (disabled) 219 exit (0); 220 221 /* ensure original outputs restored for target */ 222 reset_output (); 223 224 /* now exec the bit to instrument and run the target ... */ 225 // (void) execve( *narglist, narglist, origenvp); 226 (void) execvp (*narglist, narglist); 227 228 /* exec failed; no experiment to delete */ 229 /* restore output for collector */ 230 set_output (); 231 char *em = strerror (errno); 232 if (em == NULL) 233 dbe_write (2, GTXT ("execve of %s failed: errno = %d\n"), narglist[0], errno); 234 else 235 dbe_write (2, GTXT ("execve of %s failed: %s\n"), narglist[0], em); 236 exit (1); 237} 238