diff options
Diffstat (limited to 'gprofng/src/count.cc')
-rw-r--r-- | gprofng/src/count.cc | 237 |
1 files changed, 237 insertions, 0 deletions
diff --git a/gprofng/src/count.cc b/gprofng/src/count.cc new file mode 100644 index 00000000000..6005a49d5e5 --- /dev/null +++ b/gprofng/src/count.cc @@ -0,0 +1,237 @@ +/* Copyright (C) 2021 Free Software Foundation, Inc. + Contributed by Oracle. + + This file is part of GNU Binutils. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +#include "config.h" +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <strings.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <errno.h> +#include <i18n.h> +#include <Elf.h> +#include <collctrl.h> +#include <StringBuilder.h> +#include "collect.h" + +/* get_count_data -- format exec of bit to do the real work */ +void +collect::get_count_data () +{ + char command[8192]; + char *s; + struct stat statbuf; + + // reserve space for original args, plus 30 arguments to bit + nargs = origargc + 30; + char **narglist = (char **) calloc (nargs, sizeof (char *)); + arglist = narglist; + + // construct the command for bit + snprintf (command, sizeof (command), NTXT ("%s"), run_dir); + s = strstr_r (command, NTXT ("/bin")); + if (s != NULL) + { + // build command line for launching it + snprintf (s, sizeof (command) - (s - command), NTXT ("/lib/compilers/bit")); + if (stat (command, &statbuf) == -1) + { + // if bit command does not exist there + char *first_look = strdup (command); + snprintf (command, sizeof (command), NTXT ("%s"), run_dir); + s = strstr (command, NTXT ("/bin")); + snprintf (s, sizeof (command) - (s - command), NTXT ("/prod/bin/bit")); + if (stat (command, &statbuf) == -1) + { + // if bit command does not exist + dbe_write (2, GTXT ("bit is not installed as `%s' or `%s'\nNo experiment is possible\n"), first_look, command); + exit (2); + } + free (first_look); + } + *arglist++ = strdup (command); + } + else + { + dbe_write (2, GTXT ("collect can't find install bin directory\n")); + exit (1); + } + + // Tell it to collect data + *arglist++ = NTXT ("collect"); + + // add the flag for real-data vs. static data + switch (cc->get_count ()) + { + case -1: + *arglist++ = NTXT ("-i"); + *arglist++ = NTXT ("static"); + *arglist++ = NTXT ("-M"); + break; + case 1: + *arglist++ = NTXT ("-M"); + *arglist++ = NTXT ("-u"); + break; + default: + abort (); + } + + // tell bit to produce an experiment + *arglist++ = NTXT ("-e"); + + // now copy an edited list of collect options to the arglist + char **oargv = origargv; + + // skip the "collect" + oargv++; + int argc = 1; + while (argc != targ_index) + { + char *p = *oargv; + switch (p[1]) + { + // pass these arguments along, with parameter + case 'o': + case 'd': + case 'g': + case 'A': + case 'C': + case 'O': + case 'N': + *arglist++ = *oargv++; + *arglist++ = *oargv++; + argc = argc + 2; + break; + case 'I': + *arglist++ = *oargv++; // set the -I flag + *arglist++ = *oargv; // and the directory name + *arglist++ = NTXT ("-d"); // and the -d flag + *arglist++ = *oargv++; // to the same directory name + argc = argc + 2; + break; + case 'n': + case 'v': + // pass these arguments along as is + *arglist++ = *oargv++; + argc = argc + 1; + break; + case 'x': + // skip one argument + oargv++; + argc++; + break; + case 'c': + case 'L': + case 'y': + case 'l': + case 'F': + case 'j': + case 'J': + case 'p': + case 's': + case 'h': + case 'S': + case 'm': + case 'M': + case 'H': + case 'r': + case 'i': + // skip two arguments + oargv++; + oargv++; + argc = argc + 2; + break; + case 'R': + case 'Z': + default: + // these should never get this far + dbe_write (2, GTXT ("unexpected argument %s\n"), p); + abort (); + } + } + + // now copy the target and its arguments + if (access (prog_name, X_OK) != 0) // not found + *arglist++ = *oargv++; + else + { + oargv++; + *arglist++ = prog_name; + } + while (*oargv != NULL) + *arglist++ = *oargv++; + + /* now we have the full argument list composed; if verbose, print it */ + if ((verbose == 1) || (disabled)) + { + /* describe the experiment */ + char *ccret = cc->show (0); + if (ccret != NULL) + { + writeStr (2, ccret); + free (ccret); + } + ccret = cc->show_expt (); + if (ccret != NULL) + { + /* write this to stdout */ + writeStr (1, ccret); + free (ccret); + } + /* print the arguments to bit */ + arglist = narglist; + StringBuilder sb; + sb.append (NTXT ("Exec argv[] = ")); + for (int ret = 0; ret < nargs; ret++) + { + if (narglist[ret] == NULL) + break; + if (ret > 0) + sb.append (NTXT (" ")); + sb.append (narglist[ret]); + } + sb.append (NTXT ("\n\n")); + write (2, sb.toString (), sb.length ()); + } + + /* check for dry run */ + if (disabled) + exit (0); + + /* ensure original outputs restored for target */ + reset_output (); + + /* now exec the bit to instrument and run the target ... */ + // (void) execve( *narglist, narglist, origenvp); + (void) execvp (*narglist, narglist); + + /* exec failed; no experiment to delete */ + /* restore output for collector */ + set_output (); + char *em = strerror (errno); + if (em == NULL) + dbe_write (2, GTXT ("execve of %s failed: errno = %d\n"), narglist[0], errno); + else + dbe_write (2, GTXT ("execve of %s failed: %s\n"), narglist[0], em); + exit (1); +} |