Branch data Line data Source code
1 : : // systemtap translator/driver
2 : : // Copyright (C) 2005-2013 Red Hat Inc.
3 : : // Copyright (C) 2005 IBM Corp.
4 : : // Copyright (C) 2006 Intel Corporation.
5 : : //
6 : : // This file is part of systemtap, and is free software. You can
7 : : // redistribute it and/or modify it under the terms of the GNU General
8 : : // Public License (GPL); either version 2, or (at your option) any
9 : : // later version.
10 : :
11 : : #include "config.h"
12 : : #include "staptree.h"
13 : : #include "parse.h"
14 : : #include "elaborate.h"
15 : : #include "translate.h"
16 : : #include "buildrun.h"
17 : : #include "session.h"
18 : : #include "hash.h"
19 : : #include "cache.h"
20 : : #include "util.h"
21 : : #include "coveragedb.h"
22 : : #include "rpm_finder.h"
23 : : #include "task_finder.h"
24 : : #include "csclient.h"
25 : : #include "remote.h"
26 : : #include "tapsets.h"
27 : : #include "setupdwfl.h"
28 : :
29 : : #include <libintl.h>
30 : : #include <locale.h>
31 : :
32 : : #include "stap-probe.h"
33 : :
34 : : #include <cstdlib>
35 : :
36 : : extern "C" {
37 : : #include <glob.h>
38 : : #include <unistd.h>
39 : : #include <signal.h>
40 : : #include <sys/utsname.h>
41 : : #include <sys/times.h>
42 : : #include <sys/time.h>
43 : : #include <sys/stat.h>
44 : : #include <time.h>
45 : : #include <unistd.h>
46 : : #include <wordexp.h>
47 : : }
48 : :
49 : : using namespace std;
50 : :
51 : : static void
52 : 9536 : uniq_list(list<string>& l)
53 : : {
54 [ + - ]: 9536 : set<string> s;
55 [ + - ]: 9536 : list<string>::iterator i = l.begin();
56 [ + - ][ + + ]: 30144 : while (i != l.end())
57 [ + - ][ + + ]: 20608 : if (s.insert(*i).second)
58 : 16830 : ++i;
59 : : else
60 [ + - ][ + - ]: 13314 : i = l.erase(i);
61 : 9536 : }
62 : :
63 : : static void
64 : 1015 : printscript(systemtap_session& s, ostream& o)
65 : : {
66 [ + + ]: 1015 : if (s.listing_mode)
67 : : {
68 : : // We go through some heroic measures to produce clean output.
69 : : // Record the alias and probe pointer as <name, set<derived_probe *> >
70 [ + - ]: 62 : map<string,set<derived_probe *> > probe_list;
71 : :
72 : : // Pre-process the probe alias
73 [ + + ]: 12271 : for (unsigned i=0; i<s.probes.size(); i++)
74 : : {
75 [ + - ]: 12209 : assert_no_interrupts();
76 : :
77 : 12209 : derived_probe* p = s.probes[i];
78 : : // NB: p->basest() is not so interesting;
79 : : // p->almost_basest() doesn't quite work, so ...
80 [ + - ]: 12209 : vector<probe*> chain;
81 [ + - ]: 12209 : p->collect_derivation_chain (chain);
82 [ + - ]: 12209 : probe* second = (chain.size()>1) ? chain[chain.size()-2] : chain[0];
83 : :
84 [ - + ]: 12209 : if (s.verbose > 5) {
85 [ # # ][ # # ]: 0 : p->printsig(cerr); cerr << endl;
86 [ # # ][ # # ]: 0 : cerr << "chain[" << chain.size() << "]:" << endl;
[ # # ][ # # ]
87 [ # # ]: 0 : for (unsigned j=0; j<chain.size(); j++)
88 : : {
89 [ # # ][ # # ]: 0 : cerr << " [" << j << "]: " << endl;
[ # # ][ # # ]
90 [ # # ][ # # ]: 0 : cerr << "\tlocations[" << chain[j]->locations.size() << "]:" << endl;
[ # # ][ # # ]
91 [ # # ]: 0 : for (unsigned k=0; k<chain[j]->locations.size(); k++)
92 : : {
93 [ # # ][ # # ]: 0 : cerr << "\t [" << k << "]: ";
[ # # ]
94 [ # # ]: 0 : chain[j]->locations[k]->print(cerr);
95 [ # # ]: 0 : cerr << endl;
96 : : }
97 [ # # ]: 0 : const probe_alias *a = chain[j]->get_alias();
98 [ # # ]: 0 : if (a)
99 : : {
100 [ # # ][ # # ]: 0 : cerr << "\taliases[" << a->alias_names.size() << "]:" << endl;
[ # # ][ # # ]
101 [ # # ]: 0 : for (unsigned k=0; k<a->alias_names.size(); k++)
102 : : {
103 [ # # ][ # # ]: 0 : cerr << "\t [" << k << "]: ";
[ # # ]
104 [ # # ]: 0 : a->alias_names[k]->print(cerr);
105 [ # # ]: 0 : cerr << endl;
106 : : }
107 : : }
108 : : }
109 : : }
110 : :
111 [ + - ]: 12209 : stringstream tmps;
112 : : // XXX PR14297 make this more accurate wrt complex wildcard expansions
113 [ + - ]: 12209 : const probe_point *a = second->get_alias_loc();
114 [ + + ]: 12209 : if (a)
115 : : {
116 [ + - ]: 81 : a->print(tmps);
117 : : }
118 : : else
119 : : {
120 [ - + ]: 12128 : assert (second->locations.size() >= 1);
121 [ + - ]: 12128 : second->locations[0]->print(tmps); // XXX: choosing only one location is less arbitrary here than in get_alias_loc(), but still ...
122 : : }
123 [ + - ]: 12209 : string pp = tmps.str();
124 : :
125 : : // Now duplicate-eliminate. An alias may have expanded to
126 : : // several actual derived probe points, but we only want to
127 : : // print the alias head name once.
128 [ + - ][ + - ]: 12209 : probe_list[pp].insert(p);
129 [ + - ][ + - ]: 12209 : }
[ + - ]
130 : :
131 : : // print probe name and variables if there
132 [ + - ][ + - ]: 5211 : for (map<string, set<derived_probe *> >::iterator it=probe_list.begin(); it!=probe_list.end(); ++it)
[ + + ]
133 : : {
134 [ + - ][ + - ]: 5149 : o << it->first; // probe name or alias
135 : :
136 : : // Print the locals and arguments for -L mode only
137 [ + + ]: 5149 : if (s.listing_mode_vars)
138 : : {
139 [ + - ]: 4768 : map<string,unsigned> var_count; // format <"name:type",count>
140 [ + - ]: 4768 : map<string,unsigned> arg_count;
141 [ + - ]: 4768 : list<string> var_list;
142 [ + - ]: 4768 : list<string> arg_list;
143 : : // traverse set<derived_probe *> to collect all locals and arguments
144 [ + - ][ + - ]: 16593 : for (set<derived_probe *>::iterator ix=it->second.begin(); ix!=it->second.end(); ++ix)
[ + - ][ + - ]
[ + + ]
145 : : {
146 : 11825 : derived_probe* p = *ix;
147 : : // collect available locals of the probe
148 [ + + ]: 11850 : for (unsigned j=0; j<p->locals.size(); j++)
149 : : {
150 [ + - ]: 25 : stringstream tmps;
151 : 25 : vardecl* v = p->locals[j];
152 [ + - ]: 25 : v->printsig (tmps);
153 [ + - ][ + - ]: 25 : var_count[tmps.str()]++;
[ + - ]
154 [ + - ][ + - ]: 25 : var_list.push_back(tmps.str());
[ + - ]
155 [ + - ]: 25 : }
156 : : // collect arguments of the probe if there
157 [ + - ]: 11825 : list<string> arg_set;
158 [ + - ]: 11825 : p->getargs(arg_set);
159 [ + - ][ + - ]: 32408 : for (list<string>::iterator ia=arg_set.begin(); ia!=arg_set.end(); ++ia) {
[ + + ]
160 [ + - ]: 20583 : arg_count[*ia]++;
161 [ + - ]: 20583 : arg_list.push_back(*ia);
162 : : }
163 [ + - ]: 11825 : }
164 : :
165 [ + - ]: 4768 : uniq_list(arg_list);
166 [ + - ]: 4768 : uniq_list(var_list);
167 : :
168 : : // print the set-intersection only
169 [ + - ][ + - ]: 4793 : for (list<string>::iterator ir=var_list.begin(); ir!=var_list.end(); ++ir)
[ + + ]
170 [ + - ][ + - ]: 25 : if (var_count.find(*ir)->second == it->second.size()) // print locals
[ + - ][ + - ]
[ + - ]
171 [ + - ][ + - ]: 25 : o << " " << *ir;
172 [ + - ][ + - ]: 21573 : for (list<string>::iterator ir=arg_list.begin(); ir!=arg_list.end(); ++ir)
[ + + ]
173 [ + - ][ + - ]: 16805 : if (arg_count.find(*ir)->second == it->second.size()) // print arguments
[ + - ][ + - ]
[ + + ]
174 [ + - ][ + - ]: 14391 : o << " " << *ir;
[ + - ][ + - ]
[ + - ][ + - ]
175 : : }
176 [ + - ]: 5149 : o << endl;
177 [ + - ]: 62 : }
178 : : }
179 : : else
180 : : {
181 [ + + ]: 953 : if (s.embeds.size() > 0)
182 : 459 : o << _("# global embedded code") << endl;
183 [ + + ]: 5065 : for (unsigned i=0; i<s.embeds.size(); i++)
184 : : {
185 : 4112 : assert_no_interrupts();
186 : 4112 : embeddedcode* ec = s.embeds[i];
187 : 4112 : ec->print (o);
188 : 4112 : o << endl;
189 : : }
190 : :
191 [ + + ]: 953 : if (s.globals.size() > 0)
192 : 430 : o << _("# globals") << endl;
193 [ + + ]: 4725 : for (unsigned i=0; i<s.globals.size(); i++)
194 : : {
195 : 3772 : assert_no_interrupts();
196 : 3772 : vardecl* v = s.globals[i];
197 : 3772 : v->printsig (o);
198 [ + + ][ + + ]: 3772 : if (s.verbose && v->init)
199 : : {
200 : 216 : o << " = ";
201 : 216 : v->init->print(o);
202 : : }
203 : 3772 : o << endl;
204 : : }
205 : :
206 [ + + ]: 953 : if (s.functions.size() > 0)
207 : 779 : o << _("# functions") << endl;
208 [ + - ][ + - ]: 20307 : for (map<string,functiondecl*>::iterator it = s.functions.begin(); it != s.functions.end(); it++)
[ + + ]
209 : : {
210 [ + - ]: 19354 : assert_no_interrupts();
211 [ + - ]: 19354 : functiondecl* f = it->second;
212 [ + - ]: 19354 : f->printsig (o);
213 [ + - ]: 19354 : o << endl;
214 [ + + ]: 19354 : if (f->locals.size() > 0)
215 [ + - ][ + - ]: 1560 : o << _(" # locals") << endl;
216 [ + + ]: 21629 : for (unsigned j=0; j<f->locals.size(); j++)
217 : : {
218 : 2275 : vardecl* v = f->locals[j];
219 [ + - ]: 2275 : o << " ";
220 [ + - ]: 2275 : v->printsig (o);
221 [ + - ]: 2275 : o << endl;
222 : : }
223 [ + + ]: 19354 : if (s.verbose)
224 : : {
225 [ + - ]: 18359 : f->body->print (o);
226 [ + - ]: 18359 : o << endl;
227 : : }
228 : : }
229 : :
230 [ + - ]: 953 : if (s.probes.size() > 0)
231 : 953 : o << _("# probes") << endl;
232 [ + + ]: 342736 : for (unsigned i=0; i<s.probes.size(); i++)
233 : : {
234 : 341783 : assert_no_interrupts();
235 : 341783 : derived_probe* p = s.probes[i];
236 : 341783 : p->printsig (o);
237 : 341783 : o << endl;
238 [ + + ]: 341783 : if (p->locals.size() > 0)
239 : 48816 : o << _(" # locals") << endl;
240 [ + + ]: 451601 : for (unsigned j=0; j<p->locals.size(); j++)
241 : : {
242 : 109818 : vardecl* v = p->locals[j];
243 : 109818 : o << " ";
244 : 109818 : v->printsig (o);
245 : 109818 : o << endl;
246 : : }
247 [ + + ]: 341783 : if (s.verbose)
248 : : {
249 : 78440 : p->body->print (o);
250 : 78440 : o << endl;
251 : : }
252 : : }
253 : : }
254 : 1015 : }
255 : :
256 : :
257 : : int pending_interrupts;
258 : :
259 : : extern "C"
260 : 250 : void handle_interrupt (int sig)
261 : : {
262 : : // This might be nice, but we don't know our current verbosity...
263 : : // clog << _F("Received signal %d", sig) << endl << flush;
264 : 250 : kill_stap_spawn(SIGTERM);
265 : :
266 : 250 : pending_interrupts ++;
267 : : // Absorb the first two signals. This used to be one, but when
268 : : // stap is run under sudo, and then interrupted, sudo relays a
269 : : // redundant copy of the signal to stap, leading to an unclean shutdown.
270 [ - + ]: 250 : if (pending_interrupts > 2) // XXX: should be configurable? time-based?
271 : : {
272 : 0 : char msg[] = "Too many interrupts received, exiting.\n";
273 [ # # ]: 0 : int rc = write (2, msg, sizeof(msg)-1);
274 : : if (rc) {/* Do nothing; we don't care if our last gasp went out. */ ;}
275 : 0 : _exit (1);
276 : : }
277 : 250 : }
278 : :
279 : :
280 : : void
281 : 2413 : setup_signals (sighandler_t handler)
282 : : {
283 : : struct sigaction sa;
284 : :
285 : 2413 : memset(&sa, 0, sizeof(sa));
286 : 2413 : sa.sa_handler = handler;
287 : 2413 : sigemptyset (&sa.sa_mask);
288 [ + - ]: 2413 : if (handler != SIG_IGN)
289 : : {
290 : 2413 : sigaddset (&sa.sa_mask, SIGHUP);
291 : 2413 : sigaddset (&sa.sa_mask, SIGPIPE);
292 : 2413 : sigaddset (&sa.sa_mask, SIGINT);
293 : 2413 : sigaddset (&sa.sa_mask, SIGTERM);
294 : 2413 : sigaddset (&sa.sa_mask, SIGXFSZ);
295 : 2413 : sigaddset (&sa.sa_mask, SIGXCPU);
296 : : }
297 : 2413 : sa.sa_flags = SA_RESTART;
298 : :
299 : 2413 : sigaction (SIGHUP, &sa, NULL);
300 : 2413 : sigaction (SIGPIPE, &sa, NULL);
301 : 2413 : sigaction (SIGINT, &sa, NULL);
302 : 2413 : sigaction (SIGTERM, &sa, NULL);
303 : 2413 : sigaction (SIGXFSZ, &sa, NULL);
304 : 2413 : sigaction (SIGXCPU, &sa, NULL);
305 : 2413 : }
306 : :
307 : :
308 : : // Compilation passes 0 through 4
309 : : static int
310 : 2194 : passes_0_4 (systemtap_session &s)
311 : : {
312 : 2194 : int rc = 0;
313 : :
314 : : // If we don't know the release, there's no hope either locally or on a server.
315 [ + - ][ - + ]: 2194 : if (s.kernel_release.empty())
316 : : {
317 [ # # ][ # # ]: 0 : if (s.kernel_build_tree.empty())
318 [ # # ][ # # ]: 0 : cerr << _("ERROR: kernel release isn't specified") << endl;
319 : : else
320 [ # # ][ # # ]: 0 : cerr << _F("ERROR: kernel release isn't found in \"%s\"",
[ # # ][ # # ]
321 [ # # ]: 0 : s.kernel_build_tree.c_str()) << endl;
322 : 0 : return 1;
323 : : }
324 : :
325 : : // Perform passes 0 through 4 using a compile server?
326 [ + - ][ + + ]: 2194 : if (! s.specified_servers.empty ())
327 : : {
328 : : #if HAVE_NSS
329 [ + - ]: 39 : compile_server_client client (s);
330 [ + + ]: 39 : int rc = client.passes_0_4 ();
331 : : // Need to give a user a better diagnostic, if she didn't
332 : : // even ask for a server
333 [ + + ][ - + ]: 36 : if (rc && s.automatic_server_mode) {
334 [ # # ][ # # ]: 0 : cerr << _("Note: --use-server --unprivileged was selected because of stapusr membership.") << endl;
335 : : }
336 [ + - ]: 39 : return rc;
337 : : #else
338 : : s.print_warning("Without NSS, using a compile-server is not supported by this version of systemtap");
339 : : // This cannot be an attempt to use a server after a local compile failed
340 : : // since --use-server-on-error is locked to 'no' if we don't have
341 : : // NSS.
342 : : assert (! s.try_server ());
343 : : #endif
344 : : }
345 : :
346 : : // PASS 0: setting up
347 : 2155 : s.verbose = s.perpass_verbose[0];
348 : 2155 : PROBE1(stap, pass0__start, &s);
349 : :
350 : : // For PR1477, we used to override $PATH and $LC_ALL and other stuff
351 : : // here. We seem to use complete pathnames in
352 : : // buildrun.cxx/tapsets.cxx now, so this is not necessary. Further,
353 : : // it interferes with util.cxx:find_executable(), used for $PATH
354 : : // resolution.
355 : :
356 [ + - ][ + - ]: 2155 : s.kernel_base_release.assign(s.kernel_release, 0, s.kernel_release.find('-'));
357 : :
358 : : // Update various paths to include the sysroot, if provided.
359 [ + - ][ - + ]: 2155 : if (!s.sysroot.empty())
360 : : {
361 [ # # ][ # # ]: 0 : if (s.update_release_sysroot && !s.sysroot.empty())
[ # # ][ # # ]
362 [ # # ][ # # ]: 0 : s.kernel_build_tree = s.sysroot + s.kernel_build_tree;
[ # # ]
363 [ # # ][ # # ]: 0 : debuginfo_path_insert_sysroot(s.sysroot);
[ # # ]
364 : : }
365 : :
366 : : // Now that no further changes to s.kernel_build_tree can occur, let's use it.
367 [ + + ][ + - ]: 2155 : if ((rc = s.parse_kernel_config ()) != 0
[ + - ][ + - ]
[ + - ][ - + ]
[ - + ]
368 : : || (rc = s.parse_kernel_exports ()) != 0
369 : : || (rc = s.parse_kernel_functions ()) != 0)
370 : : {
371 : : // Try again with a server
372 [ # # ]: 0 : s.set_try_server ();
373 : 0 : return rc;
374 : : }
375 : :
376 : : // Create the name of the C source file within the temporary
377 : : // directory. Note the _src prefix, explained in
378 : : // buildrun.cxx:compile_pass()
379 [ + - ][ + - ]: 2154 : s.translated_source = string(s.tmpdir) + "/" + s.module_name + "_src.c";
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
380 : :
381 : 2154 : PROBE1(stap, pass0__end, &s);
382 : :
383 : : struct tms tms_before;
384 : 2154 : times (& tms_before);
385 : : struct timeval tv_before;
386 : 2154 : gettimeofday (&tv_before, NULL);
387 : :
388 : : // PASS 1a: PARSING LIBRARY SCRIPTS
389 : 2154 : PROBE1(stap, pass1a__start, &s);
390 : :
391 : : // We need to handle the library scripts first because this pass
392 : : // gathers information on .stpm files that might be needed to
393 : : // parse the user script.
394 : :
395 : : // We need to first ascertain the status of the user script, though.
396 : : struct stat user_file_stat;
397 : 2154 : int user_file_stat_rc = -1;
398 : :
399 [ + - ][ + + ]: 2154 : if (s.script_file == "-")
400 : : {
401 : 277 : user_file_stat_rc = fstat (STDIN_FILENO, & user_file_stat);
402 : : }
403 [ + - ][ + + ]: 1877 : else if (s.script_file != "")
404 : : {
405 [ + - ]: 1614 : user_file_stat_rc = stat (s.script_file.c_str(), & user_file_stat);
406 : : }
407 : : // otherwise, rc is 0 for a command line script
408 : :
409 [ + - ]: 2154 : vector<string> version_suffixes;
410 [ + - ]: 2154 : if (s.runtime_mode == systemtap_session::kernel_runtime)
411 : : {
412 : : // Construct kernel-versioning search path
413 [ + - ]: 2154 : string kvr = s.kernel_release;
414 : :
415 : : // add full kernel-version-release (2.6.NN-FOOBAR)
416 [ + - ][ + - ]: 2154 : version_suffixes.push_back ("/" + kvr);
[ + - ]
417 : :
418 : : // add kernel version (2.6.NN)
419 [ + - ][ - + ]: 2154 : if (kvr != s.kernel_base_release)
420 : : {
421 [ # # ]: 0 : kvr = s.kernel_base_release;
422 [ # # ][ # # ]: 0 : version_suffixes.push_back ("/" + kvr);
[ # # ]
423 : : }
424 : :
425 : : // add kernel family (2.6)
426 [ + - ]: 2154 : string::size_type dot1_index = kvr.find ('.');
427 [ + - ]: 2154 : string::size_type dot2_index = kvr.rfind ('.');
428 [ + + ][ + - ]: 6462 : while (dot2_index > dot1_index && dot2_index != string::npos)
[ + + ]
429 : : {
430 [ + - ]: 4308 : kvr.erase(dot2_index);
431 [ + - ][ + - ]: 4308 : version_suffixes.push_back ("/" + kvr);
[ + - ]
432 [ + - ]: 4308 : dot2_index = kvr.rfind ('.');
433 [ + - ]: 2154 : }
434 : : }
435 : :
436 : : // add empty string as last element
437 [ + - ][ + - ]: 2154 : version_suffixes.push_back ("");
[ + - ]
438 : :
439 : : // Add arch variants of every path, just before each
440 : 2154 : const string& arch = s.architecture;
441 [ + + ]: 10770 : for (unsigned i=0; i<version_suffixes.size(); i+=2)
442 : : version_suffixes.insert(version_suffixes.begin() + i,
443 [ + - ][ + - ]: 8616 : version_suffixes[i] + "/" + arch);
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
444 : :
445 : : // Add runtime variants of every path, before everything else
446 [ + - ]: 2154 : string runtime_prefix;
447 [ + - ]: 2154 : if (s.runtime_mode == systemtap_session::kernel_runtime)
448 [ + - ]: 2154 : runtime_prefix = "/linux";
449 [ # # ]: 0 : else if (s.runtime_mode == systemtap_session::dyninst_runtime)
450 [ # # ]: 0 : runtime_prefix = "/dyninst";
451 [ + - ][ + - ]: 2154 : if (!runtime_prefix.empty())
452 [ + + ]: 19386 : for (unsigned i=0; i<version_suffixes.size(); i+=2)
453 : : version_suffixes.insert(version_suffixes.begin() + i/2,
454 [ + - ][ + - ]: 17232 : runtime_prefix + version_suffixes[i]);
[ + - ][ + - ]
[ + - ]
455 : :
456 : : // First, parse .stpm files on the include path. We need to have the
457 : : // resulting macro definitions available for parsing library files,
458 : : // but since .stpm files can consist only of '@define' constructs,
459 : : // we can parse each one without reference to the others.
460 [ + - ]: 2154 : set<pair<dev_t, ino_t> > seen_library_macro_files;
461 [ + - ]: 2154 : set<string> seen_library_macro_files_names;
462 : :
463 [ + + ]: 4355 : for (unsigned i=0; i<s.include_path.size(); i++)
464 : : {
465 : : // now iterate upon it
466 [ + + ]: 37417 : for (unsigned k=0; k<version_suffixes.size(); k++)
467 : : {
468 : : glob_t globbuf;
469 [ + - ][ + - ]: 35216 : string dir = s.include_path[i] + version_suffixes[k] + "/*.stpm";
[ + - ]
470 [ + - ]: 35216 : int r = glob(dir.c_str (), 0, NULL, & globbuf);
471 [ + - ][ - + ]: 35216 : if (r == GLOB_NOSPACE || r == GLOB_ABORTED)
472 : 0 : rc ++;
473 : : // GLOB_NOMATCH is acceptable
474 : :
475 : 35216 : unsigned prev_s_library_files = s.library_files.size();
476 : :
477 [ + + ]: 39524 : for (unsigned j=0; j<globbuf.gl_pathc; j++)
478 : : {
479 [ + - ]: 4308 : assert_no_interrupts();
480 : :
481 : : struct stat tapset_file_stat;
482 : 4308 : int stat_rc = stat (globbuf.gl_pathv[j], & tapset_file_stat);
483 [ + - ][ + + ]: 4308 : if (stat_rc == 0 && user_file_stat_rc == 0 &&
[ + + ][ - + ]
484 : : user_file_stat.st_dev == tapset_file_stat.st_dev &&
485 : : user_file_stat.st_ino == tapset_file_stat.st_ino)
486 : : {
487 : : cerr
488 [ # # ][ # # ]: 0 : << _F("usage error: macro tapset file '%s' cannot be run directly as a session script.",
[ # # ]
489 [ # # ]: 0 : globbuf.gl_pathv[j]) << endl;
490 : 0 : rc ++;
491 : : }
492 : :
493 : : // PR11949: duplicate-eliminate tapset files
494 [ + - ]: 4308 : if (stat_rc == 0)
495 : : {
496 : : pair<dev_t,ino_t> here = make_pair(tapset_file_stat.st_dev,
497 [ + - ]: 4308 : tapset_file_stat.st_ino);
498 [ + - ][ + - ]: 4308 : if (seen_library_macro_files.find(here) != seen_library_macro_files.end()) {
[ - + ]
499 [ # # ]: 0 : if (s.verbose>2)
500 [ # # ][ # # ]: 0 : clog << _F("Skipping tapset \"%s\", duplicate inode.", globbuf.gl_pathv[j]) << endl;
[ # # ][ # # ]
501 : 0 : continue;
502 : : }
503 [ + - ]: 4308 : seen_library_macro_files.insert (here);
504 : : }
505 : :
506 : : // PR12443: duplicate-eliminate harder
507 [ + - ]: 4308 : string full_path = globbuf.gl_pathv[j];
508 [ + - ]: 4308 : string tapset_base = s.include_path[i]; // not dir; it has arch suffixes too
509 [ + - ][ + - ]: 4308 : if (full_path.size() > tapset_base.size()) {
[ + - ]
510 [ + - ][ + - ]: 4308 : string tail_part = full_path.substr(tapset_base.size());
511 [ + - ][ + - ]: 4308 : if (seen_library_macro_files_names.find (tail_part) != seen_library_macro_files_names.end()) {
[ - + ]
512 [ # # ]: 0 : if (s.verbose>2)
513 [ # # ][ # # ]: 0 : clog << _F("Skipping tapset \"%s\", duplicate name.", globbuf.gl_pathv[j]) << endl;
[ # # ][ # # ]
514 : 0 : continue;
515 : : }
516 [ + - ][ + - ]: 4308 : seen_library_macro_files_names.insert (tail_part);
[ + - ]
517 : : }
518 : :
519 [ + + ]: 4308 : if (s.verbose>2)
520 [ + - ][ + - ]: 2 : clog << _F("Processing tapset \"%s\"", globbuf.gl_pathv[j]) << endl;
[ + - ][ + - ]
521 : :
522 [ + - ][ + - ]: 4308 : stapfile* f = parse_library_macros (s, globbuf.gl_pathv[j]);
[ + - ]
523 [ - + ]: 4308 : if (f == 0)
524 : 0 : s.print_warning("macro tapset '" + string(globbuf.gl_pathv[j])
525 [ # # ][ # # ]: 0 : + "' has errors, and will be skipped."); // TODOXXX internationalization?
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
526 : : else
527 [ + - ]: 4308 : s.library_files.push_back (f);
528 [ + - ][ - + ]: 4308 : }
[ + - ][ + - ]
529 : :
530 : 35216 : unsigned next_s_library_files = s.library_files.size();
531 [ + + ][ + + ]: 35216 : if (s.verbose>1 && globbuf.gl_pathc > 0)
532 : : //TRANSLATORS: Searching through directories, 'processed' means 'examined so far'
533 [ + - ][ + - ]: 80 : clog << _F("Searched for library macro files: \"%s\", found: %zu, processed: %u",
[ + - ][ + - ]
534 : : dir.c_str(), globbuf.gl_pathc,
535 [ + - ]: 40 : (next_s_library_files-prev_s_library_files)) << endl;
536 : :
537 : 35216 : globfree (&globbuf);
538 [ + - ]: 35216 : }
539 : : }
540 : :
541 : : // Next, gather and parse the library files.
542 [ + - ]: 2154 : set<pair<dev_t, ino_t> > seen_library_files;
543 [ + - ]: 2154 : set<string> seen_library_files_names;
544 : :
545 [ + + ]: 4355 : for (unsigned i=0; i<s.include_path.size(); i++)
546 : : {
547 : : // now iterate upon it
548 [ + + ]: 37417 : for (unsigned k=0; k<version_suffixes.size(); k++)
549 : : {
550 : : glob_t globbuf;
551 [ + - ][ + - ]: 35216 : string dir = s.include_path[i] + version_suffixes[k] + "/*.stp";
[ + - ]
552 [ + - ]: 35216 : int r = glob(dir.c_str (), 0, NULL, & globbuf);
553 [ + - ][ - + ]: 35216 : if (r == GLOB_NOSPACE || r == GLOB_ABORTED)
554 : 0 : rc ++;
555 : : // GLOB_NOMATCH is acceptable
556 : :
557 : 35216 : unsigned prev_s_library_files = s.library_files.size();
558 : :
559 [ + + ]: 220574 : for (unsigned j=0; j<globbuf.gl_pathc; j++)
560 : : {
561 [ + - ]: 185358 : assert_no_interrupts();
562 : :
563 : : struct stat tapset_file_stat;
564 : 185358 : int stat_rc = stat (globbuf.gl_pathv[j], & tapset_file_stat);
565 [ + - ][ + + ]: 185358 : if (stat_rc == 0 && user_file_stat_rc == 0 &&
[ + + ][ + + ]
566 : : user_file_stat.st_dev == tapset_file_stat.st_dev &&
567 : : user_file_stat.st_ino == tapset_file_stat.st_ino)
568 : : {
569 : : cerr
570 [ + - ][ + - ]: 2 : << _F("usage error: tapset file '%s' cannot be run directly as a session script.",
[ + - ]
571 [ + - ]: 1 : globbuf.gl_pathv[j]) << endl;
572 : 1 : rc ++;
573 : : }
574 : :
575 : : // PR11949: duplicate-eliminate tapset files
576 [ + - ]: 185358 : if (stat_rc == 0)
577 : : {
578 : : pair<dev_t,ino_t> here = make_pair(tapset_file_stat.st_dev,
579 [ + - ]: 185358 : tapset_file_stat.st_ino);
580 [ + - ][ + - ]: 185358 : if (seen_library_files.find(here) != seen_library_files.end()) {
[ - + ]
581 [ # # ]: 0 : if (s.verbose>2)
582 [ # # ][ # # ]: 0 : clog << _F("Skipping tapset \"%s\", duplicate inode.", globbuf.gl_pathv[j]) << endl;
[ # # ][ # # ]
583 : 0 : continue;
584 : : }
585 [ + - ]: 185358 : seen_library_files.insert (here);
586 : : }
587 : :
588 : : // PR12443: duplicate-eliminate harder
589 [ + - ]: 185358 : string full_path = globbuf.gl_pathv[j];
590 [ + - ]: 185358 : string tapset_base = s.include_path[i]; // not dir; it has arch suffixes too
591 [ + - ][ + - ]: 185358 : if (full_path.size() > tapset_base.size()) {
[ + - ]
592 [ + - ][ + - ]: 185358 : string tail_part = full_path.substr(tapset_base.size());
593 [ + - ][ + - ]: 185358 : if (seen_library_files_names.find (tail_part) != seen_library_files_names.end()) {
[ - + ]
594 [ # # ]: 0 : if (s.verbose>2)
595 [ # # ][ # # ]: 0 : clog << _F("Skipping tapset \"%s\", duplicate name.", globbuf.gl_pathv[j]) << endl;
[ # # ][ # # ]
596 : 0 : continue;
597 : : }
598 [ + - ][ + - ]: 185358 : seen_library_files_names.insert (tail_part);
[ + - ]
599 : : }
600 : :
601 [ + + ]: 185358 : if (s.verbose>2)
602 [ + - ][ + - ]: 86 : clog << _F("Processing tapset \"%s\"", globbuf.gl_pathv[j]) << endl;
[ + - ][ + - ]
603 : :
604 : : // NB: we don't need to restrict privilege only for /usr/share/systemtap, i.e.,
605 : : // excluding user-specified $XDG_DATA_DIRS. That's because stapdev gets
606 : : // root-equivalent privileges anyway; stapsys and stapusr use a remote compilation
607 : : // with a trusted environment, where client-side $XDG_DATA_DIRS are not passed.
608 : :
609 [ + - ][ + - ]: 185358 : stapfile* f = parse (s, globbuf.gl_pathv[j], true /* privileged */);
[ + - ]
610 [ + + ]: 185358 : if (f == 0)
611 : 2 : s.print_warning("tapset '" + string(globbuf.gl_pathv[j])
612 [ + - ][ + - ]: 2 : + "' has errors, and will be skipped."); // TODOXXX internationalization?
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
613 : : else
614 [ + - ]: 185358 : s.library_files.push_back (f);
615 [ + - ][ - + ]: 185358 : }
[ + - ][ + - ]
616 : :
617 : 35216 : unsigned next_s_library_files = s.library_files.size();
618 [ + + ][ + + ]: 35216 : if (s.verbose>1 && globbuf.gl_pathc > 0)
619 : : //TRANSLATORS: Searching through directories, 'processed' means 'examined so far'
620 [ + - ][ + - ]: 160 : clog << _F("Searched: \"%s\", found: %zu, processed: %u",
[ + - ][ + - ]
621 : : dir.c_str(), globbuf.gl_pathc,
622 [ + - ]: 80 : (next_s_library_files-prev_s_library_files)) << endl;
623 : :
624 : 35216 : globfree (& globbuf);
625 [ + - ]: 35216 : }
626 : : }
627 [ + - ][ + + ]: 2154 : if (s.num_errors())
628 : 1 : rc ++;
629 : :
630 : : // PASS 1b: PARSING USER SCRIPT
631 : 2154 : PROBE1(stap, pass1b__start, &s);
632 : :
633 [ + - ][ + + ]: 2154 : if (s.script_file == "-")
634 : : {
635 [ + - ]: 277 : s.user_file = parse (s, cin, s.guru_mode);
636 : : }
637 [ + - ][ + + ]: 1877 : else if (s.script_file != "")
638 : : {
639 [ + - ]: 1614 : s.user_file = parse (s, s.script_file, s.guru_mode);
640 : : }
641 : : else
642 : : {
643 [ + - ]: 263 : istringstream ii (s.cmdline_script);
644 [ + - ][ + - ]: 263 : s.user_file = parse (s, ii, s.guru_mode);
645 : : }
646 [ + + ]: 2154 : if (s.user_file == 0)
647 : : {
648 : : // Syntax errors already printed.
649 : 118 : rc ++;
650 : : }
651 : :
652 [ + + ][ + + ]: 2154 : if (rc == 0 && s.last_pass == 1)
653 : : {
654 [ + - ][ + - ]: 816 : cout << _("# parse tree dump") << endl;
655 [ + - ]: 816 : s.user_file->print (cout);
656 [ + - ]: 816 : cout << endl;
657 [ + + ]: 816 : if (s.verbose)
658 [ + + ]: 89 : for (unsigned i=0; i<s.library_files.size(); i++)
659 : : {
660 [ + - ]: 88 : s.library_files[i]->print (cout);
661 [ + - ]: 88 : cout << endl;
662 : : }
663 : : }
664 : :
665 : : struct tms tms_after;
666 : 2154 : times (& tms_after);
667 : 2154 : unsigned _sc_clk_tck = sysconf (_SC_CLK_TCK);
668 : : struct timeval tv_after;
669 : 2154 : gettimeofday (&tv_after, NULL);
670 : :
671 : : #define TIMESPRINT "in " << \
672 : : (tms_after.tms_cutime + tms_after.tms_utime \
673 : : - tms_before.tms_cutime - tms_before.tms_utime) * 1000 / (_sc_clk_tck) << "usr/" \
674 : : << (tms_after.tms_cstime + tms_after.tms_stime \
675 : : - tms_before.tms_cstime - tms_before.tms_stime) * 1000 / (_sc_clk_tck) << "sys/" \
676 : : << ((tv_after.tv_sec - tv_before.tv_sec) * 1000 + \
677 : : ((long)tv_after.tv_usec - (long)tv_before.tv_usec) / 1000) << "real ms."
678 : :
679 : : // syntax errors, if any, are already printed
680 [ + + ]: 2154 : if (s.verbose)
681 : : {
682 : : // XXX also include a count of helper macro files loaded (.stpm)?
683 [ + - ]: 106 : clog << "Pass 1: parsed user script and "
684 [ + - ]: 106 : << s.library_files.size()
685 [ + - ]: 106 : << " library script(s) "
686 [ + - ][ + - ]: 212 : << getmemusage()
[ + - ]
687 [ + - ][ + - ]: 106 : << TIMESPRINT
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
688 [ + - ]: 106 : << endl;
689 : : }
690 : :
691 [ + + ][ + - ]: 2154 : if (rc && !s.listing_mode)
692 [ + - ][ + - ]: 120 : cerr << _("Pass 1: parse failed. [man error::pass1]") << endl;
693 : :
694 : 2154 : PROBE1(stap, pass1__end, &s);
695 : :
696 [ + - ]: 2154 : assert_no_interrupts();
697 [ + + ][ + + ]: 2154 : if (rc || s.last_pass == 1) return rc;
698 : :
699 : 1218 : times (& tms_before);
700 : 1218 : gettimeofday (&tv_before, NULL);
701 : :
702 : : // PASS 2: ELABORATION
703 : 1218 : s.verbose = s.perpass_verbose[1];
704 : 1218 : PROBE1(stap, pass2__start, &s);
705 [ + - ]: 1218 : rc = semantic_pass (s);
706 : :
707 : : // Dump a list of known probe point types, if requested.
708 [ - + ]: 1218 : if (s.dump_probe_types)
709 [ # # ][ # # ]: 0 : s.pattern_root->dump (s);
[ # # ]
710 : :
711 [ + + ][ + + ]: 1218 : if (s.listing_mode || (rc == 0 && s.last_pass == 2))
[ + + ]
712 [ + - ]: 201 : printscript(s, cout);
713 : :
714 : 1218 : times (& tms_after);
715 : 1218 : gettimeofday (&tv_after, NULL);
716 : :
717 [ + + ][ + - ]: 1218 : if (s.verbose) clog << "Pass 2: analyzed script: "
718 [ + - ][ + - ]: 105 : << s.probes.size() << " probe(s), "
719 [ + - ][ + - ]: 105 : << s.functions.size() << " function(s), "
[ + - ]
720 [ + - ][ + - ]: 105 : << s.embeds.size() << " embed(s), "
721 [ + - ][ + - ]: 105 : << s.globals.size() << " global(s) "
722 [ + - ][ + - ]: 210 : << getmemusage()
[ + - ]
723 [ + - ][ + - ]: 105 : << TIMESPRINT
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
724 [ + - ]: 105 : << endl;
725 : :
726 [ + + ][ + + ]: 1218 : if (rc && !s.listing_mode && !s.try_server ())
[ + - ][ + + ]
727 [ + - ][ + - ]: 186 : cerr << _("Pass 2: analysis failed. [man error::pass2]") << endl;
728 : :
729 : 1218 : PROBE1(stap, pass2__end, &s);
730 : :
731 [ + + ]: 1218 : assert_no_interrupts();
732 [ + + ][ + + ]: 1213 : if (rc || s.listing_mode || s.last_pass == 2) return rc;
[ + + ]
733 : :
734 [ + - ]: 831 : rc = prepare_translate_pass (s);
735 [ + - ]: 831 : assert_no_interrupts();
736 [ - + ]: 831 : if (rc) return rc;
737 : :
738 : : // Generate hash. There isn't any point in generating the hash
739 : : // if last_pass is 2, since we'll quit before using it.
740 [ + + ]: 831 : if (s.use_script_cache)
741 : : {
742 [ + - ]: 814 : ostringstream o;
743 : : unsigned saved_verbose;
744 : :
745 : : {
746 : : // Make sure we're in verbose mode, so that printscript()
747 : : // will output function/probe bodies.
748 : 814 : saved_verbose = s.verbose;
749 : 814 : s.verbose = 3;
750 [ + - ]: 814 : printscript(s, o); // Print script to 'o'
751 : 814 : s.verbose = saved_verbose;
752 : : }
753 : :
754 : : // Generate hash
755 [ + - ][ + - ]: 814 : find_script_hash (s, o.str());
[ + - ]
756 : :
757 : : // See if we can use cached source/module.
758 [ + - ][ + + ]: 814 : if (get_script_from_cache(s))
759 : : {
760 : : // We may still need to build uprobes, if it's not also cached.
761 [ - + ]: 186 : if (s.need_uprobes)
762 [ # # ]: 0 : rc = uprobes_pass(s);
763 : :
764 : : // If our last pass isn't 5, we're done (since passes 3 and
765 : : // 4 just generate what we just pulled out of the cache).
766 [ + - ]: 186 : assert_no_interrupts();
767 [ + - ][ + + ]: 186 : if (rc || s.last_pass < 5) return rc;
768 : :
769 : : // Short-circuit to pass 5.
770 : 791 : return 0;
771 [ + - ][ + + ]: 814 : }
772 : : }
773 : :
774 : : // PASS 3: TRANSLATION
775 : 645 : s.verbose = s.perpass_verbose[2];
776 : 645 : times (& tms_before);
777 : 645 : gettimeofday (&tv_before, NULL);
778 : 645 : PROBE1(stap, pass3__start, &s);
779 : :
780 [ + - ]: 645 : rc = translate_pass (s);
781 [ + + ][ + + ]: 645 : if (! rc && s.last_pass == 3)
782 : : {
783 [ + - ][ + - ]: 19 : ifstream i (s.translated_source.c_str());
784 [ + - ][ + - ]: 19 : cout << i.rdbuf();
[ + - ]
785 : : }
786 : :
787 : 645 : times (& tms_after);
788 : 645 : gettimeofday (&tv_after, NULL);
789 : :
790 [ + + ]: 645 : if (s.verbose)
791 [ + - ]: 83 : clog << "Pass 3: translated to C into \""
792 [ + - ]: 83 : << s.translated_source
793 [ + - ]: 83 : << "\" "
794 [ + - ][ + - ]: 166 : << getmemusage()
[ + - ]
795 [ + - ][ + - ]: 83 : << TIMESPRINT
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
796 [ + - ]: 83 : << endl;
797 : :
798 [ + + ][ + - ]: 645 : if (rc && ! s.try_server ())
[ + + ]
799 [ + - ][ + - ]: 2 : cerr << _("Pass 3: translation failed. [man error::pass3]") << endl;
800 : :
801 : 645 : PROBE1(stap, pass3__end, &s);
802 : :
803 [ + - ]: 645 : assert_no_interrupts();
804 [ + + ][ + + ]: 645 : if (rc || s.last_pass == 3) return rc;
805 : :
806 : : // PASS 4: COMPILATION
807 : 624 : s.verbose = s.perpass_verbose[3];
808 : 624 : times (& tms_before);
809 : 624 : gettimeofday (&tv_before, NULL);
810 : 624 : PROBE1(stap, pass4__start, &s);
811 : :
812 [ + + ]: 624 : if (s.use_cache)
813 : : {
814 [ + - ]: 622 : find_stapconf_hash(s);
815 [ + - ]: 622 : get_stapconf_from_cache(s);
816 : : }
817 [ + - ]: 624 : rc = compile_pass (s);
818 [ + + ][ + + ]: 624 : if (! rc && s.last_pass == 4)
819 : : {
820 [ + - ][ + + ]: 297 : cout << ((s.hash_path == "") ? s.module_filename() : s.hash_path);
[ + - ][ + - ]
[ + - ][ + - ]
821 [ + - ]: 297 : cout << endl;
822 : : }
823 : :
824 : 624 : times (& tms_after);
825 : 624 : gettimeofday (&tv_after, NULL);
826 : :
827 [ + + ][ + - ]: 624 : if (s.verbose) clog << "Pass 4: compiled C into \""
828 [ + - ][ + - ]: 166 : << s.module_filename()
[ + - ]
829 [ + - ]: 83 : << "\" "
830 [ + - ][ + - ]: 83 : << TIMESPRINT
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
831 [ + - ]: 83 : << endl;
832 : :
833 [ + + ][ + - ]: 624 : if (rc && ! s.try_server ())
[ + + ]
834 [ + - ][ + - ]: 15 : cerr << _("Pass 4: compilation failed. [man error::pass4]") << endl;
835 : :
836 : : else
837 : : {
838 : : // Update cache. Cache cleaning is kicked off at the beginning of this function.
839 [ + + ]: 609 : if (s.use_script_cache)
840 [ + - ]: 592 : add_script_to_cache(s);
841 [ + + ][ + - ]: 609 : if (s.use_cache && !s.runtime_usermode_p())
[ + + ]
842 [ + - ]: 607 : add_stapconf_to_cache(s);
843 : :
844 : : // We may need to save the module in $CWD if the cache was
845 : : // inaccessible for some reason.
846 [ + + ][ + + ]: 609 : if (! s.use_script_cache && s.last_pass == 4)
847 : 7 : s.save_module = true;
848 : :
849 : : // Copy module to the current directory.
850 [ + + ][ + - ]: 609 : if (s.save_module && !pending_interrupts)
851 : : {
852 [ + - ][ + - ]: 17 : string module_src_path = s.tmpdir + "/" + s.module_filename();
[ + - ][ + - ]
[ + - ]
853 [ + - ]: 17 : string module_dest_path = s.module_filename();
854 [ + - ][ + - ]: 17 : copy_file(module_src_path, module_dest_path, s.verbose > 1);
[ + - ]
855 : : }
856 : : }
857 : :
858 : 624 : PROBE1(stap, pass4__end, &s);
859 : :
860 [ + - ][ + - ]: 2194 : return rc;
[ + - ][ + - ]
[ + - ][ + - ]
861 : : }
862 : :
863 : : static int
864 : 475 : pass_5 (systemtap_session &s, vector<remote*> targets)
865 : : {
866 : : // PASS 5: RUN
867 : 475 : s.verbose = s.perpass_verbose[4];
868 : : struct tms tms_before;
869 : 475 : times (& tms_before);
870 : : struct timeval tv_before;
871 : 475 : gettimeofday (&tv_before, NULL);
872 : : // NB: this message is a judgement call. The other passes don't emit
873 : : // a "hello, I'm starting" message, but then the others aren't interactive
874 : : // and don't take an indefinite amount of time.
875 : 475 : PROBE1(stap, pass5__start, &s);
876 [ + + ][ + - ]: 475 : if (s.verbose) clog << _("Pass 5: starting run.") << endl;
[ + - ]
877 [ + - ]: 475 : int rc = remote::run(targets);
878 : : struct tms tms_after;
879 : 475 : times (& tms_after);
880 : 475 : unsigned _sc_clk_tck = sysconf (_SC_CLK_TCK);
881 : : struct timeval tv_after;
882 : 475 : gettimeofday (&tv_after, NULL);
883 [ + + ][ + - ]: 475 : if (s.verbose) clog << "Pass 5: run completed "
884 [ + - ][ + - ]: 72 : << TIMESPRINT
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
885 [ + - ]: 72 : << endl;
886 : :
887 [ + + ]: 475 : if (rc)
888 [ + - ][ + - ]: 101 : cerr << _("Pass 5: run failed. [man error::pass5]") << endl;
889 : : else
890 : : // Interrupting pass-5 to quit is normal, so we want an EXIT_SUCCESS below.
891 : 374 : pending_interrupts = 0;
892 : :
893 : 475 : PROBE1(stap, pass5__end, &s);
894 : :
895 : 475 : return rc;
896 : : }
897 : :
898 : : static void
899 : 2204 : cleanup (systemtap_session &s, int rc)
900 : : {
901 : : // PASS 6: cleaning up
902 : 2204 : PROBE1(stap, pass6__start, &s);
903 : :
904 [ + - ][ - + ]: 4408 : for (systemtap_session::session_map_t::iterator it = s.subsessions.begin();
905 [ + - ]: 2204 : it != s.subsessions.end(); ++it)
906 [ # # ][ # # ]: 0 : cleanup (*it->second, rc);
907 : :
908 : : // update the database information
909 [ + + ][ - + ]: 2204 : if (!rc && s.tapset_compile_coverage && !pending_interrupts) {
[ # # ]
910 : : #ifdef HAVE_LIBSQLITE3
911 : 0 : update_coverage_db(s);
912 : : #else
913 : : cerr << _("Coverage database not available without libsqlite3") << endl;
914 : : #endif
915 : : }
916 : :
917 : 2204 : PROBE1(stap, pass6__end, &s);
918 : 2204 : }
919 : :
920 : : static int
921 : 0 : passes_0_4_again_with_server (systemtap_session &s)
922 : : {
923 : : // Not a server and not already using a server.
924 [ # # ]: 0 : assert (! s.client_options);
925 [ # # ]: 0 : assert (s.specified_servers.empty ());
926 : :
927 : : // Specify default server(s).
928 [ # # ][ # # ]: 0 : s.specified_servers.push_back ("");
[ # # ]
929 : :
930 : : // Reset the previous temporary directory and start fresh
931 : 0 : s.reset_tmp_dir();
932 : :
933 : : // Try to compile again, using the server
934 : 0 : clog << _("Attempting compilation using a compile server")
935 : 0 : << endl;
936 : :
937 : 0 : int rc = passes_0_4 (s);
938 : 0 : return rc;
939 : : }
940 : :
941 : : int
942 : 2414 : main (int argc, char * const argv [])
943 : : {
944 : : // Initialize defaults.
945 : : try {
946 [ + + ]: 2414 : systemtap_session s;
947 : :
948 : 2413 : setlocale (LC_ALL, "");
949 : 2413 : bindtextdomain (PACKAGE, LOCALEDIR);
950 : 2413 : textdomain (PACKAGE);
951 : :
952 : : // Set up our handler to catch routine signals, to allow clean
953 : : // and reasonably timely exit.
954 : 2413 : setup_signals(&handle_interrupt);
955 : :
956 : : // PR13520: Parse $SYSTEMTAP_DIR/rc for extra options
957 [ + - ]: 2413 : string rc_file = s.data_path + "/rc";
958 [ + - ][ + - ]: 2413 : ifstream rcf (rc_file.c_str());
959 [ + - ]: 2413 : string rcline;
960 : : wordexp_t words;
961 : 2413 : memset (& words, 0, sizeof(words));
962 : 2413 : int rc = 0;
963 : 2413 : int linecount = 0;
964 [ + - ][ + - ]: 9592 : while (getline (rcf, rcline))
[ + + ]
965 : : {
966 : : rc = wordexp (rcline.c_str(), & words, WRDE_NOCMD|WRDE_UNDEF|
967 [ + - ][ + + ]: 7179 : (linecount > 0 ? WRDE_APPEND : 0));
[ + - ]
968 : : // NB: WRDE_APPEND automagically reallocates words.* as more options are added.
969 : 7179 : linecount ++;
970 [ - + ]: 7179 : if (rc) break;
971 : : }
972 : 2413 : int extended_argc = words.we_wordc + argc;
973 : 2413 : char **extended_argv = (char**) calloc (extended_argc + 1, sizeof(char*));
974 [ + - ][ - + ]: 2413 : if (rc || !extended_argv)
975 : : {
976 [ # # ][ # # ]: 0 : clog << _F("Error processing extra options in %s", rc_file.c_str());
[ # # ][ # # ]
977 : 0 : return EXIT_FAILURE;
978 : : }
979 : : // Copy over the arguments *by reference*, first the ones from the rc file.
980 : 2413 : char **p = & extended_argv[0];
981 : 2413 : *p++ = argv[0];
982 [ + + ]: 14378 : for (unsigned i=0; i<words.we_wordc; i++) *p++ = words.we_wordv[i];
983 [ + + ]: 9609 : for (int j=1; j<argc; j++) *p++ = argv[j];
984 : 2413 : *p++ = NULL;
985 : :
986 : : // Process the command line.
987 [ + + ]: 2413 : rc = s.parse_cmdline (extended_argc, extended_argv);
988 [ + + ]: 2341 : if (rc != 0)
989 : 91 : return rc;
990 : :
991 [ + + ][ + + ]: 2250 : if (words.we_wordc > 0 && s.verbose > 1)
992 [ + - ][ + - ]: 18 : clog << _F("Extra options in %s: %d\n", rc_file.c_str(), (int)words.we_wordc);
[ + - ][ + - ]
993 : :
994 : : // Check for options conflicts. Exits if errors are detected.
995 [ + + ]: 2250 : s.check_options (extended_argc, extended_argv);
996 : :
997 : : // We don't need these strings any more.
998 : 2213 : wordfree (& words);
999 : 2213 : free (extended_argv);
1000 : :
1001 : : // arguments parsed; get down to business
1002 [ + + ]: 2213 : if (s.verbose > 1)
1003 [ + - ]: 20 : s.version ();
1004 : :
1005 : : // Need to send the verbose message here, rather than in the session ctor, since
1006 : : // we didn't know if verbose was set.
1007 [ + - ][ + + ]: 2213 : if (rc == 0 && s.verbose>1)
1008 [ + - ][ + - ]: 20 : clog << _F("Created temporary directory \"%s\"", s.tmpdir.c_str()) << endl;
[ + - ][ + - ]
[ + - ]
1009 : :
1010 : : // Prepare connections for each specified remote target.
1011 [ + - ]: 2213 : vector<remote*> targets;
1012 : 2213 : bool fake_remote=false;
1013 [ + - ][ + + ]: 2213 : if (s.remote_uris.empty())
1014 : : {
1015 : 2206 : fake_remote=true;
1016 [ + - ][ + - ]: 2206 : s.remote_uris.push_back("direct:");
[ + - ]
1017 : : }
1018 [ + + ][ + + ]: 4427 : for (unsigned i = 0; rc == 0 && i < s.remote_uris.size(); ++i)
[ + + ]
1019 : : {
1020 : : // PR13354: pass remote id#/url only in non --remote=HOST cases
1021 : 2214 : remote *target = remote::create(s, s.remote_uris[i],
1022 [ + + ][ + - ]: 2214 : fake_remote ? -1 : (int)i);
1023 [ + + ]: 2214 : if (target)
1024 [ + - ]: 2213 : targets.push_back(target);
1025 : : else
1026 : 1 : rc = 1;
1027 : : }
1028 : :
1029 : : // Discover and loop over each unique session created by the remote targets.
1030 [ + - ]: 2213 : set<systemtap_session*> sessions;
1031 [ + + ]: 4426 : for (unsigned i = 0; i < targets.size(); ++i)
1032 [ + - ]: 2213 : sessions.insert(targets[i]->get_session());
1033 [ + - ][ + + ]: 12865 : for (set<systemtap_session*>::iterator it = sessions.begin();
[ + + + + ]
[ + + ]
1034 [ + - ][ + + ]: 8458 : rc == 0 && !pending_interrupts && it != sessions.end(); ++it)
[ # # ]
1035 : : {
1036 : 2212 : systemtap_session& ss = **it;
1037 [ + + ]: 2212 : if (ss.verbose > 1)
1038 [ + - ][ + - ]: 40 : clog << _F("Session arch: %s release: %s",
[ + - ][ + - ]
[ + - ]
1039 [ + - ]: 20 : ss.architecture.c_str(), ss.kernel_release.c_str()) << endl;
1040 : :
1041 : : #if HAVE_NSS
1042 : : // If requested, query server status. This is independent of other tasks.
1043 [ + - ]: 2212 : query_server_status (ss);
1044 : :
1045 : : // If requested, manage trust of servers. This is independent of other tasks.
1046 [ + - ]: 2212 : manage_server_trust (ss);
1047 : : #endif
1048 : :
1049 : : // Run the passes only if a script has been specified. The requirement for
1050 : : // a script has already been checked in systemtap_session::check_options.
1051 : : // Run the passes also if a dump of supported probe types has been requested via a server.
1052 [ + + ][ - + ]: 2212 : if (ss.have_script || (ss.dump_probe_types && ! s.specified_servers.empty ()))
[ # # ][ # # ]
[ + + ]
1053 : : {
1054 : : // Run passes 0-4 for each unique session,
1055 : : // either locally or using a compile-server.
1056 [ + - ]: 2194 : ss.init_try_server ();
1057 [ + + ][ + + ]: 2194 : if ((rc = passes_0_4 (ss)))
1058 : : {
1059 : : // Compilation failed.
1060 : : // Try again using a server if appropriate.
1061 [ - + ]: 377 : if (ss.try_server ())
1062 [ # # ]: 0 : rc = passes_0_4_again_with_server (ss);
1063 : : }
1064 : : }
1065 [ - + ]: 18 : else if (ss.dump_probe_types)
1066 : : {
1067 : : // Dump a list of known probe point types, if requested.
1068 [ # # ]: 0 : register_standard_tapsets(ss);
1069 [ # # ][ # # ]: 0 : ss.pattern_root->dump (ss);
[ # # ]
1070 : : }
1071 : : }
1072 : :
1073 : : // Run pass 5, if requested
1074 [ + + ][ + + ]: 2204 : if (rc == 0 && s.have_script && s.last_pass >= 5 && ! pending_interrupts)
[ + + ][ + - ]
1075 [ + - ][ + - ]: 475 : rc = pass_5 (s, targets);
[ + - ]
1076 : :
1077 : : // Pass 6. Cleanup
1078 [ + + ]: 4408 : for (unsigned i = 0; i < targets.size(); ++i)
1079 [ + - ][ + - ]: 2204 : delete targets[i];
1080 [ + - ]: 2204 : cleanup (s, rc);
1081 : :
1082 [ + + ]: 2204 : assert_no_interrupts();
1083 [ + + ][ + - ]: 2543 : return (rc) ? EXIT_FAILURE : EXIT_SUCCESS;
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1084 : : }
1085 : 18 : catch (const interrupt_exception& e) {
1086 : : // User entered ctrl-c, exit quietly.
1087 : 18 : return EXIT_FAILURE;
1088 : : }
1089 : 47 : catch (const exit_exception& e) {
1090 : : // Exiting for any quiet reason.
1091 : 47 : return e.rc;
1092 : : }
1093 : 126 : catch (const runtime_error &e) {
1094 : : // Some other uncaught runtime_error exception.
1095 [ - + ][ - + ]: 63 : cerr << e.what() << endl;
1096 : 63 : return EXIT_FAILURE;
1097 : : }
1098 [ + + + + ]: 130 : catch (...) {
1099 : : // Catch all other unknown exceptions.
1100 [ - + ][ - + ]: 1 : cerr << _("ERROR: caught unknown exception!") << endl;
1101 : 1 : return EXIT_FAILURE;
1102 : : }
1103 [ + - ][ + - ]: 7242 : }
1104 : :
1105 : : /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
|