]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gprofng/src/count.cc
Update year range in gprofng copyright notices
[thirdparty/binutils-gdb.git] / gprofng / src / count.cc
1 /* Copyright (C) 2021-2023 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 */
38 void
39 collect::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 }