]> sourceware.org Git - systemtap.git/blame - main.cxx
Fix the 'if.exp' testcase so that the second test result matters.
[systemtap.git] / main.cxx
CommitLineData
f4b28491 1// systemtap translator/driver
4e78c716 2// Copyright (C) 2005-2014 Red Hat Inc.
f12b2552 3// Copyright (C) 2005 IBM Corp.
77a5c1f9 4// Copyright (C) 2006 Intel Corporation.
69c68955
FCE
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.
2b066ec1
FCE
10
11#include "config.h"
85007c04
DB
12#include "staptree.h"
13#include "parse.h"
14#include "elaborate.h"
15#include "translate.h"
16#include "buildrun.h"
dc38c0ae 17#include "session.h"
85007c04
DB
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"
daa75206 25#include "remote.h"
b82d77b4 26#include "tapsets.h"
05fb3e0c 27#include "setupdwfl.h"
85007c04 28
52c2652f 29#if ENABLE_NLS
79bc39ab
LB
30#include <libintl.h>
31#include <locale.h>
52c2652f 32#endif
79bc39ab 33
0f5d597d 34#include "stap-probe.h"
aa4d21c0 35
24cb178f 36#include <cstdlib>
73267b89 37
85007c04
DB
38extern "C" {
39#include <glob.h>
40#include <unistd.h>
41#include <signal.h>
42#include <sys/utsname.h>
43#include <sys/times.h>
44#include <sys/time.h>
45#include <sys/stat.h>
46#include <time.h>
47#include <unistd.h>
222e16ed 48#include <wordexp.h>
85007c04
DB
49}
50
51using namespace std;
52
40a50254
JS
53static void
54uniq_list(list<string>& l)
e2012a7a 55{
40a50254
JS
56 set<string> s;
57 list<string>::iterator i = l.begin();
58 while (i != l.end())
59 if (s.insert(*i).second)
60 ++i;
61 else
62 i = l.erase(i);
85007c04 63}
2dce8c42 64
85007c04
DB
65static void
66printscript(systemtap_session& s, ostream& o)
67{
bba368c5
JL
68 if (s.dump_mode == systemtap_session::dump_matched_probes ||
69 s.dump_mode == systemtap_session::dump_matched_probes_vars)
85007c04
DB
70 {
71 // We go through some heroic measures to produce clean output.
72 // Record the alias and probe pointer as <name, set<derived_probe *> >
73 map<string,set<derived_probe *> > probe_list;
6e683641 74
85007c04
DB
75 // Pre-process the probe alias
76 for (unsigned i=0; i<s.probes.size(); i++)
77 {
e19ebcf7 78 assert_no_interrupts();
85007c04
DB
79
80 derived_probe* p = s.probes[i];
ede0102c
JS
81 vector<probe*> chain;
82 p->collect_derivation_chain (chain);
83
8159bf55 84 if (s.verbose > 2) {
8159bf55
FCE
85 p->printsig(cerr); cerr << endl;
86 cerr << "chain[" << chain.size() << "]:" << endl;
87 for (unsigned j=0; j<chain.size(); j++)
88 {
89 cerr << " [" << j << "]: " << endl;
90 cerr << "\tlocations[" << chain[j]->locations.size() << "]:" << endl;
91 for (unsigned k=0; k<chain[j]->locations.size(); k++)
92 {
93 cerr << "\t [" << k << "]: ";
94 chain[j]->locations[k]->print(cerr);
95 cerr << endl;
96 }
97 const probe_alias *a = chain[j]->get_alias();
98 if (a)
99 {
100 cerr << "\taliases[" << a->alias_names.size() << "]:" << endl;
101 for (unsigned k=0; k<a->alias_names.size(); k++)
102 {
103 cerr << "\t [" << k << "]: ";
104 a->alias_names[k]->print(cerr);
105 cerr << endl;
106 }
107 }
108 }
7977a734 109 }
eb55dce6
JS
110
111 const string& pp = lex_cast(*p->script_location());
112
113 // PR16730: We should only list probes that can be traced back to the
114 // user's spec, not any auxiliary probes in the tapsets.
ba48c27a
AJ
115 // Also, do not want to the probes that are from the additional
116 // scripts (-E SCRIPT) to be listed.
1ee0d3ba
JL
117 if (!s.is_primary_probe(p))
118 continue;
85007c04
DB
119
120 // Now duplicate-eliminate. An alias may have expanded to
121 // several actual derived probe points, but we only want to
122 // print the alias head name once.
123 probe_list[pp].insert(p);
124 }
125
126 // print probe name and variables if there
127 for (map<string, set<derived_probe *> >::iterator it=probe_list.begin(); it!=probe_list.end(); ++it)
128 {
129 o << it->first; // probe name or alias
130
131 // Print the locals and arguments for -L mode only
bba368c5 132 if (s.dump_mode == systemtap_session::dump_matched_probes_vars)
85007c04
DB
133 {
134 map<string,unsigned> var_count; // format <"name:type",count>
135 map<string,unsigned> arg_count;
136 list<string> var_list;
137 list<string> arg_list;
138 // traverse set<derived_probe *> to collect all locals and arguments
139 for (set<derived_probe *>::iterator ix=it->second.begin(); ix!=it->second.end(); ++ix)
140 {
141 derived_probe* p = *ix;
142 // collect available locals of the probe
143 for (unsigned j=0; j<p->locals.size(); j++)
144 {
145 stringstream tmps;
146 vardecl* v = p->locals[j];
147 v->printsig (tmps);
148 var_count[tmps.str()]++;
149 var_list.push_back(tmps.str());
150 }
151 // collect arguments of the probe if there
152 list<string> arg_set;
153 p->getargs(arg_set);
154 for (list<string>::iterator ia=arg_set.begin(); ia!=arg_set.end(); ++ia) {
155 arg_count[*ia]++;
156 arg_list.push_back(*ia);
157 }
158 }
159
160 uniq_list(arg_list);
161 uniq_list(var_list);
162
163 // print the set-intersection only
164 for (list<string>::iterator ir=var_list.begin(); ir!=var_list.end(); ++ir)
165 if (var_count.find(*ir)->second == it->second.size()) // print locals
166 o << " " << *ir;
167 for (list<string>::iterator ir=arg_list.begin(); ir!=arg_list.end(); ++ir)
168 if (arg_count.find(*ir)->second == it->second.size()) // print arguments
169 o << " " << *ir;
170 }
171 o << endl;
172 }
173 }
174 else
2dce8c42 175 {
85007c04 176 if (s.embeds.size() > 0)
79bc39ab 177 o << _("# global embedded code") << endl;
85007c04
DB
178 for (unsigned i=0; i<s.embeds.size(); i++)
179 {
e19ebcf7 180 assert_no_interrupts();
85007c04
DB
181 embeddedcode* ec = s.embeds[i];
182 ec->print (o);
183 o << endl;
184 }
2dce8c42 185
85007c04 186 if (s.globals.size() > 0)
79bc39ab 187 o << _("# globals") << endl;
85007c04
DB
188 for (unsigned i=0; i<s.globals.size(); i++)
189 {
e19ebcf7 190 assert_no_interrupts();
85007c04
DB
191 vardecl* v = s.globals[i];
192 v->printsig (o);
193 if (s.verbose && v->init)
194 {
195 o << " = ";
196 v->init->print(o);
197 }
198 o << endl;
199 }
200
201 if (s.functions.size() > 0)
79bc39ab 202 o << _("# functions") << endl;
85007c04
DB
203 for (map<string,functiondecl*>::iterator it = s.functions.begin(); it != s.functions.end(); it++)
204 {
e19ebcf7 205 assert_no_interrupts();
85007c04
DB
206 functiondecl* f = it->second;
207 f->printsig (o);
208 o << endl;
209 if (f->locals.size() > 0)
79bc39ab 210 o << _(" # locals") << endl;
85007c04
DB
211 for (unsigned j=0; j<f->locals.size(); j++)
212 {
213 vardecl* v = f->locals[j];
214 o << " ";
215 v->printsig (o);
216 o << endl;
217 }
218 if (s.verbose)
219 {
220 f->body->print (o);
221 o << endl;
222 }
223 }
224
225 if (s.probes.size() > 0)
79bc39ab 226 o << _("# probes") << endl;
85007c04
DB
227 for (unsigned i=0; i<s.probes.size(); i++)
228 {
e19ebcf7 229 assert_no_interrupts();
85007c04
DB
230 derived_probe* p = s.probes[i];
231 p->printsig (o);
232 o << endl;
233 if (p->locals.size() > 0)
79bc39ab 234 o << _(" # locals") << endl;
85007c04
DB
235 for (unsigned j=0; j<p->locals.size(); j++)
236 {
237 vardecl* v = p->locals[j];
238 o << " ";
239 v->printsig (o);
240 o << endl;
241 }
242 if (s.verbose)
243 {
244 p->body->print (o);
245 o << endl;
246 }
247 }
2dce8c42 248 }
85007c04 249}
e2012a7a 250
e2012a7a 251
85007c04
DB
252int pending_interrupts;
253
254extern "C"
255void handle_interrupt (int sig)
256{
c9c8c406
JS
257 // This might be nice, but we don't know our current verbosity...
258 // clog << _F("Received signal %d", sig) << endl << flush;
878b2f3f
CM
259 kill_stap_spawn(SIGTERM);
260
85007c04 261 pending_interrupts ++;
536a1b69
FCE
262 // Absorb the first two signals. This used to be one, but when
263 // stap is run under sudo, and then interrupted, sudo relays a
264 // redundant copy of the signal to stap, leading to an unclean shutdown.
265 if (pending_interrupts > 2) // XXX: should be configurable? time-based?
85007c04
DB
266 {
267 char msg[] = "Too many interrupts received, exiting.\n";
268 int rc = write (2, msg, sizeof(msg)-1);
269 if (rc) {/* Do nothing; we don't care if our last gasp went out. */ ;}
270 _exit (1);
271 }
272}
273
274
275void
276setup_signals (sighandler_t handler)
277{
278 struct sigaction sa;
279
11c6c509 280 memset(&sa, 0, sizeof(sa));
85007c04
DB
281 sa.sa_handler = handler;
282 sigemptyset (&sa.sa_mask);
283 if (handler != SIG_IGN)
284 {
285 sigaddset (&sa.sa_mask, SIGHUP);
286 sigaddset (&sa.sa_mask, SIGPIPE);
287 sigaddset (&sa.sa_mask, SIGINT);
288 sigaddset (&sa.sa_mask, SIGTERM);
5ed19be2
DB
289 sigaddset (&sa.sa_mask, SIGXFSZ);
290 sigaddset (&sa.sa_mask, SIGXCPU);
85007c04
DB
291 }
292 sa.sa_flags = SA_RESTART;
293
294 sigaction (SIGHUP, &sa, NULL);
295 sigaction (SIGPIPE, &sa, NULL);
296 sigaction (SIGINT, &sa, NULL);
297 sigaction (SIGTERM, &sa, NULL);
5ed19be2
DB
298 sigaction (SIGXFSZ, &sa, NULL);
299 sigaction (SIGXCPU, &sa, NULL);
e2012a7a 300}
6e683641 301
85007c04 302
3d0a328d
JS
303static void*
304sdt_benchmark_thread(void* p)
305{
306 unsigned long i = *(unsigned long*)p;
26d48584 307 PROBE(stap, benchmark__thread__start);
3d0a328d 308 while (i--)
bc7f17fb 309 PROBE1(stap, benchmark, i);
f8e839e8 310 PROBE(stap, benchmark__thread__end);
3d0a328d
JS
311 return NULL;
312}
313
314
315static int
316run_sdt_benchmark(systemtap_session& s)
317{
318 unsigned long loops = s.benchmark_sdt_loops ?: 10000000;
319 unsigned long threads = s.benchmark_sdt_threads ?: 1;
320
a7160c2b
JS
321 if (s.verbose > 0)
322 clog << _F("Beginning SDT benchmark with %lu loops in %lu threads.",
323 loops, threads) << endl;
3d0a328d
JS
324
325 struct tms tms_before, tms_after;
326 struct timeval tv_before, tv_after;
327 unsigned _sc_clk_tck = sysconf (_SC_CLK_TCK);
328 times (& tms_before);
329 gettimeofday (&tv_before, NULL);
330
26d48584 331 PROBE(stap, benchmark__start);
bc7f17fb 332
3d0a328d
JS
333 pthread_t pthreads[threads];
334 for (unsigned long i = 0; i < threads; ++i)
335 pthread_create(&pthreads[i], NULL, sdt_benchmark_thread, &loops);
336 for (unsigned long i = 0; i < threads; ++i)
337 pthread_join(pthreads[i], NULL);
338
f8e839e8 339 PROBE(stap, benchmark__end);
bc7f17fb 340
3d0a328d
JS
341 times (& tms_after);
342 gettimeofday (&tv_after, NULL);
a7160c2b
JS
343 if (s.verbose > 0)
344 clog << _F("Completed SDT benchmark in %ldusr/%ldsys/%ldreal ms.",
561d4ebd
FCE
345 (long)(tms_after.tms_utime - tms_before.tms_utime) * 1000 / _sc_clk_tck,
346 (long)(tms_after.tms_stime - tms_before.tms_stime) * 1000 / _sc_clk_tck,
347 (long)((tv_after.tv_sec - tv_before.tv_sec) * 1000 +
a7160c2b
JS
348 ((long)tv_after.tv_usec - (long)tv_before.tv_usec) / 1000))
349 << endl;
3d0a328d
JS
350
351 return EXIT_SUCCESS;
352}
353
354
44edbcd6 355// Compilation passes 0 through 4
85007c04
DB
356static int
357passes_0_4 (systemtap_session &s)
358{
359 int rc = 0;
daa75206 360
504d2b61
JS
361 // If we don't know the release, there's no hope either locally or on a server.
362 if (s.kernel_release.empty())
363 {
364 if (s.kernel_build_tree.empty())
365 cerr << _("ERROR: kernel release isn't specified") << endl;
366 else
46a1a151
JS
367 cerr << _F("ERROR: kernel release isn't found in \"%s\"",
368 s.kernel_build_tree.c_str()) << endl;
504d2b61
JS
369 return 1;
370 }
371
85007c04
DB
372 // Perform passes 0 through 4 using a compile server?
373 if (! s.specified_servers.empty ())
374 {
0d1534e8 375#if HAVE_NSS
85007c04 376 compile_server_client client (s);
4e78c716 377 return client.passes_0_4 ();
0d1534e8 378#else
4e78c716
DB
379 s.print_warning(_("Without NSS, using a compile-server is not supported by this version of systemtap"));
380
3e1ec884
DB
381 // This cannot be an attempt to use a server after a local compile failed
382 // since --use-server-on-error is locked to 'no' if we don't have
383 // NSS.
384 assert (! s.try_server ());
4e78c716 385 s.print_warning(_("Ignoring --use-server"));
0d1534e8 386#endif
85007c04
DB
387 }
388
389 // PASS 0: setting up
390 s.verbose = s.perpass_verbose[0];
0f5d597d 391 PROBE1(stap, pass0__start, &s);
85007c04 392
85007c04
DB
393 // For PR1477, we used to override $PATH and $LC_ALL and other stuff
394 // here. We seem to use complete pathnames in
395 // buildrun.cxx/tapsets.cxx now, so this is not necessary. Further,
396 // it interferes with util.cxx:find_executable(), used for $PATH
397 // resolution.
398
399 s.kernel_base_release.assign(s.kernel_release, 0, s.kernel_release.find('-'));
400
05fb3e0c
WF
401 // Update various paths to include the sysroot, if provided.
402 if (!s.sysroot.empty())
403 {
404 if (s.update_release_sysroot && !s.sysroot.empty())
405 s.kernel_build_tree = s.sysroot + s.kernel_build_tree;
406 debuginfo_path_insert_sysroot(s.sysroot);
407 }
408
85007c04 409 // Now that no further changes to s.kernel_build_tree can occur, let's use it.
d0923e36
NMA
410 if (s.runtime_mode == systemtap_session::kernel_runtime) {
411 if ((rc = s.parse_kernel_config ()) != 0
412 || (rc = s.parse_kernel_exports ()) != 0
413 || (rc = s.parse_kernel_functions ()) != 0)
414 {
415 // Try again with a server
416 s.set_try_server ();
417 return rc;
418 }
419 }
85007c04
DB
420
421 // Create the name of the C source file within the temporary
a4b9c3b3
FCE
422 // directory. Note the _src prefix, explained in
423 // buildrun.cxx:compile_pass()
424 s.translated_source = string(s.tmpdir) + "/" + s.module_name + "_src.c";
85007c04 425
0f5d597d 426 PROBE1(stap, pass0__end, &s);
85007c04
DB
427
428 struct tms tms_before;
429 times (& tms_before);
430 struct timeval tv_before;
431 gettimeofday (&tv_before, NULL);
432
e7c60c35 433 // PASS 1a: PARSING LIBRARY SCRIPTS
0f5d597d 434 PROBE1(stap, pass1a__start, &s);
85007c04 435
e7c60c35
SM
436 // We need to handle the library scripts first because this pass
437 // gathers information on .stpm files that might be needed to
438 // parse the user script.
439
440 // We need to first ascertain the status of the user script, though.
85007c04
DB
441 struct stat user_file_stat;
442 int user_file_stat_rc = -1;
443
444 if (s.script_file == "-")
445 {
85007c04
DB
446 user_file_stat_rc = fstat (STDIN_FILENO, & user_file_stat);
447 }
448 else if (s.script_file != "")
449 {
85007c04
DB
450 user_file_stat_rc = stat (s.script_file.c_str(), & user_file_stat);
451 }
e7c60c35 452 // otherwise, rc is 0 for a command line script
f705da87 453
85007c04 454 vector<string> version_suffixes;
f705da87
JS
455 if (s.runtime_mode == systemtap_session::kernel_runtime)
456 {
457 // Construct kernel-versioning search path
458 string kvr = s.kernel_release;
459
460 // add full kernel-version-release (2.6.NN-FOOBAR)
461 version_suffixes.push_back ("/" + kvr);
462
463 // add kernel version (2.6.NN)
464 if (kvr != s.kernel_base_release)
465 {
466 kvr = s.kernel_base_release;
467 version_suffixes.push_back ("/" + kvr);
468 }
469
470 // add kernel family (2.6)
471 string::size_type dot1_index = kvr.find ('.');
472 string::size_type dot2_index = kvr.rfind ('.');
473 while (dot2_index > dot1_index && dot2_index != string::npos)
474 {
475 kvr.erase(dot2_index);
476 version_suffixes.push_back ("/" + kvr);
477 dot2_index = kvr.rfind ('.');
478 }
479 }
480
85007c04
DB
481 // add empty string as last element
482 version_suffixes.push_back ("");
483
f705da87
JS
484 // Add arch variants of every path, just before each
485 const string& arch = s.architecture;
486 for (unsigned i=0; i<version_suffixes.size(); i+=2)
487 version_suffixes.insert(version_suffixes.begin() + i,
488 version_suffixes[i] + "/" + arch);
489
490 // Add runtime variants of every path, before everything else
491 string runtime_prefix;
492 if (s.runtime_mode == systemtap_session::kernel_runtime)
493 runtime_prefix = "/linux";
494 else if (s.runtime_mode == systemtap_session::dyninst_runtime)
495 runtime_prefix = "/dyninst";
496 if (!runtime_prefix.empty())
497 for (unsigned i=0; i<version_suffixes.size(); i+=2)
498 version_suffixes.insert(version_suffixes.begin() + i/2,
499 runtime_prefix + version_suffixes[i]);
85007c04 500
fe410f52
SM
501 // First, parse .stpm files on the include path. We need to have the
502 // resulting macro definitions available for parsing library files,
503 // but since .stpm files can consist only of '@define' constructs,
504 // we can parse each one without reference to the others.
505 set<pair<dev_t, ino_t> > seen_library_macro_files;
43179f10 506 set<string> seen_library_macro_files_names;
fe410f52 507
f7a557ae
SM
508 for (unsigned i=0; i<s.include_path.size(); i++)
509 {
510 // now iterate upon it
511 for (unsigned k=0; k<version_suffixes.size(); k++)
512 {
513 glob_t globbuf;
514 string dir = s.include_path[i] + version_suffixes[k] + "/*.stpm";
515 int r = glob(dir.c_str (), 0, NULL, & globbuf);
516 if (r == GLOB_NOSPACE || r == GLOB_ABORTED)
517 rc ++;
518 // GLOB_NOMATCH is acceptable
519
fe410f52
SM
520 unsigned prev_s_library_files = s.library_files.size();
521
f7a557ae
SM
522 for (unsigned j=0; j<globbuf.gl_pathc; j++)
523 {
fe410f52 524 assert_no_interrupts();
f7a557ae 525
fe410f52
SM
526 struct stat tapset_file_stat;
527 int stat_rc = stat (globbuf.gl_pathv[j], & tapset_file_stat);
528 if (stat_rc == 0 && user_file_stat_rc == 0 &&
529 user_file_stat.st_dev == tapset_file_stat.st_dev &&
530 user_file_stat.st_ino == tapset_file_stat.st_ino)
531 {
532 cerr
533 << _F("usage error: macro tapset file '%s' cannot be run directly as a session script.",
534 globbuf.gl_pathv[j]) << endl;
535 rc ++;
f7a557ae
SM
536 }
537
fe410f52
SM
538 // PR11949: duplicate-eliminate tapset files
539 if (stat_rc == 0)
540 {
541 pair<dev_t,ino_t> here = make_pair(tapset_file_stat.st_dev,
542 tapset_file_stat.st_ino);
43179f10
FCE
543 if (seen_library_macro_files.find(here) != seen_library_macro_files.end()) {
544 if (s.verbose>2)
545 clog << _F("Skipping tapset \"%s\", duplicate inode.", globbuf.gl_pathv[j]) << endl;
546 continue;
547 }
fe410f52
SM
548 seen_library_macro_files.insert (here);
549 }
f7a557ae 550
43179f10
FCE
551 // PR12443: duplicate-eliminate harder
552 string full_path = globbuf.gl_pathv[j];
553 string tapset_base = s.include_path[i]; // not dir; it has arch suffixes too
554 if (full_path.size() > tapset_base.size()) {
555 string tail_part = full_path.substr(tapset_base.size());
556 if (seen_library_macro_files_names.find (tail_part) != seen_library_macro_files_names.end()) {
557 if (s.verbose>2)
558 clog << _F("Skipping tapset \"%s\", duplicate name.", globbuf.gl_pathv[j]) << endl;
559 continue;
560 }
561 seen_library_macro_files_names.insert (tail_part);
562 }
563
564 if (s.verbose>2)
565 clog << _F("Processing tapset \"%s\"", globbuf.gl_pathv[j]) << endl;
566
f8405ea5 567 stapfile* f = parse_library_macros (s, globbuf.gl_pathv[j]);
fe410f52 568 if (f == 0)
6522229f 569 s.print_warning(_F("macro tapset \"%s\" has errors, and will be skipped.", string(globbuf.gl_pathv[j]).c_str()));
fe410f52
SM
570 else
571 s.library_files.push_back (f);
f7a557ae
SM
572 }
573
fe410f52 574 unsigned next_s_library_files = s.library_files.size();
f7a557ae 575 if (s.verbose>1 && globbuf.gl_pathc > 0)
fe410f52 576 //TRANSLATORS: Searching through directories, 'processed' means 'examined so far'
c687e307 577 clog << _F("Searched for library macro files: \"%s\", found: %zu, processed: %u",
fe410f52
SM
578 dir.c_str(), globbuf.gl_pathc,
579 (next_s_library_files-prev_s_library_files)) << endl;
f7a557ae
SM
580
581 globfree (&globbuf);
582 }
583 }
584
585 // Next, gather and parse the library files.
ad7c8e43 586 set<pair<dev_t, ino_t> > seen_library_files;
43179f10 587 set<string> seen_library_files_names;
ad7c8e43 588
85007c04
DB
589 for (unsigned i=0; i<s.include_path.size(); i++)
590 {
f8405ea5
JS
591 unsigned tapset_flags = pf_guru | pf_squash_errors;
592
593 // The first path is special, as it's the builtin tapset.
594 // Allow all features no matter what s.compatible says.
595 if (i == 0)
596 tapset_flags |= pf_no_compatible;
597
85007c04
DB
598 // now iterate upon it
599 for (unsigned k=0; k<version_suffixes.size(); k++)
600 {
601 glob_t globbuf;
602 string dir = s.include_path[i] + version_suffixes[k] + "/*.stp";
603 int r = glob(dir.c_str (), 0, NULL, & globbuf);
604 if (r == GLOB_NOSPACE || r == GLOB_ABORTED)
3e1ec884 605 rc ++;
44edbcd6 606 // GLOB_NOMATCH is acceptable
85007c04 607
ad7c8e43 608 unsigned prev_s_library_files = s.library_files.size();
85007c04
DB
609
610 for (unsigned j=0; j<globbuf.gl_pathc; j++)
611 {
e19ebcf7 612 assert_no_interrupts();
85007c04 613
85007c04
DB
614 struct stat tapset_file_stat;
615 int stat_rc = stat (globbuf.gl_pathv[j], & tapset_file_stat);
616 if (stat_rc == 0 && user_file_stat_rc == 0 &&
617 user_file_stat.st_dev == tapset_file_stat.st_dev &&
618 user_file_stat.st_ino == tapset_file_stat.st_ino)
619 {
79bc39ab 620 cerr
46a1a151
JS
621 << _F("usage error: tapset file '%s' cannot be run directly as a session script.",
622 globbuf.gl_pathv[j]) << endl;
85007c04
DB
623 rc ++;
624 }
625
ad7c8e43
FCE
626 // PR11949: duplicate-eliminate tapset files
627 if (stat_rc == 0)
628 {
629 pair<dev_t,ino_t> here = make_pair(tapset_file_stat.st_dev,
630 tapset_file_stat.st_ino);
43179f10
FCE
631 if (seen_library_files.find(here) != seen_library_files.end()) {
632 if (s.verbose>2)
633 clog << _F("Skipping tapset \"%s\", duplicate inode.", globbuf.gl_pathv[j]) << endl;
634 continue;
635 }
ad7c8e43
FCE
636 seen_library_files.insert (here);
637 }
638
43179f10
FCE
639 // PR12443: duplicate-eliminate harder
640 string full_path = globbuf.gl_pathv[j];
641 string tapset_base = s.include_path[i]; // not dir; it has arch suffixes too
642 if (full_path.size() > tapset_base.size()) {
643 string tail_part = full_path.substr(tapset_base.size());
644 if (seen_library_files_names.find (tail_part) != seen_library_files_names.end()) {
645 if (s.verbose>2)
646 clog << _F("Skipping tapset \"%s\", duplicate name.", globbuf.gl_pathv[j]) << endl;
647 continue;
648 }
649 seen_library_files_names.insert (tail_part);
650 }
651
652 if (s.verbose>2)
653 clog << _F("Processing tapset \"%s\"", globbuf.gl_pathv[j]) << endl;
654
a16ea97d
FCE
655 // NB: we don't need to restrict privilege only for /usr/share/systemtap, i.e.,
656 // excluding user-specified $XDG_DATA_DIRS. That's because stapdev gets
657 // root-equivalent privileges anyway; stapsys and stapusr use a remote compilation
658 // with a trusted environment, where client-side $XDG_DATA_DIRS are not passed.
659
f8405ea5 660 stapfile* f = parse (s, globbuf.gl_pathv[j], tapset_flags);
2713ea24 661 if (f == 0)
6522229f 662 s.print_warning(_F("tapset \"%s\" has errors, and will be skipped", string(globbuf.gl_pathv[j]).c_str()));
ad7c8e43
FCE
663 else
664 s.library_files.push_back (f);
85007c04
DB
665 }
666
ad7c8e43
FCE
667 unsigned next_s_library_files = s.library_files.size();
668 if (s.verbose>1 && globbuf.gl_pathc > 0)
ce0f6648 669 //TRANSLATORS: Searching through directories, 'processed' means 'examined so far'
c687e307 670 clog << _F("Searched: \"%s\", found: %zu, processed: %u",
46a1a151
JS
671 dir.c_str(), globbuf.gl_pathc,
672 (next_s_library_files-prev_s_library_files)) << endl;
ad7c8e43 673
85007c04
DB
674 globfree (& globbuf);
675 }
676 }
677 if (s.num_errors())
3e1ec884 678 rc ++;
85007c04 679
e7c60c35
SM
680 // PASS 1b: PARSING USER SCRIPT
681 PROBE1(stap, pass1b__start, &s);
682
bba368c5
JL
683 // Only try to parse a user script if the user provided one, or if we have to
684 // make one (as is the case for listing mode). Otherwise, s.user_script
685 // remains NULL.
686 if (!s.script_file.empty() ||
687 !s.cmdline_script.empty() ||
688 s.dump_mode == systemtap_session::dump_matched_probes ||
689 s.dump_mode == systemtap_session::dump_matched_probes_vars)
e7c60c35 690 {
f8405ea5 691 unsigned user_flags = s.guru_mode ? pf_guru : 0;
bba368c5
JL
692 if (s.script_file == "-")
693 {
ba48c27a 694 s.user_files.push_back (parse (s, "<input>", cin, user_flags));
bba368c5
JL
695 }
696 else if (s.script_file != "")
697 {
ba48c27a 698 s.user_files.push_back (parse (s, s.script_file, user_flags));
bba368c5
JL
699 }
700 else if (s.cmdline_script != "")
701 {
702 istringstream ii (s.cmdline_script);
ba48c27a 703 s.user_files.push_back(parse (s, "<input>", ii, user_flags));
bba368c5
JL
704 }
705 else // listing mode
706 {
707 istringstream ii ("probe " + s.dump_matched_pattern + " {}");
ba48c27a 708 s.user_files.push_back (parse (s, "<input>", ii, user_flags));
bba368c5 709 }
ba48c27a
AJ
710
711 // parses the additional script(s) (-E script). does so even if in listing
712 // mode, incase there is something special in the additional script(s),
713 // like a macro or alias. give them a unique name to differentiate the
714 // scripts that were inputted.
715 unsigned count = 1;
716 for (vector<string>::iterator script = s.additional_scripts.begin(); script != s.additional_scripts.end(); script++)
717 {
718 string input_name = "<input" + lex_cast(count) + ">";
719 istringstream ii (*script);
720 s.user_files.push_back(parse (s, input_name, ii, user_flags));
721 count ++;
722 }
723
724 for(vector<stapfile*>::iterator it = s.user_files.begin(); it != s.user_files.end(); it++)
bba368c5 725 {
ba48c27a
AJ
726 if (!(*it))
727 {
728 // Syntax errors already printed.
729 rc ++;
730 }
bba368c5 731 }
e7c60c35
SM
732 }
733
7d66cd75 734 // Dump a list of probe aliases picked up, if requested
bba368c5 735 if (s.dump_mode == systemtap_session::dump_probe_aliases)
7d66cd75
JL
736 {
737 set<string> aliases;
738 vector<stapfile*>::const_iterator file;
739 for (file = s.library_files.begin();
740 file != s.library_files.end(); ++file)
741 {
742 vector<probe_alias*>::const_iterator alias;
743 for (alias = (*file)->aliases.begin();
744 alias != (*file)->aliases.end(); ++alias)
745 {
746 stringstream ss;
747 (*alias)->printsig(ss);
748 string str = ss.str();
749 if (!s.verbose && startswith(str, "_"))
750 continue;
751 aliases.insert(str);
752 }
753 }
754
755 set<string>::iterator alias;
756 for (alias = aliases.begin();
757 alias != aliases.end(); ++alias)
758 {
759 cout << *alias << endl;
760 }
761 }
762 // Dump the parse tree if this is the last pass
763 else if (rc == 0 && s.last_pass == 1)
4c263acb
SM
764 {
765 cout << _("# parse tree dump") << endl;
ba48c27a
AJ
766 for (vector<stapfile*>::iterator it = s.user_files.begin(); it != s.user_files.end(); it++)
767 (*it)->print (cout);
4c263acb
SM
768 cout << endl;
769 if (s.verbose)
770 for (unsigned i=0; i<s.library_files.size(); i++)
771 {
772 s.library_files[i]->print (cout);
773 cout << endl;
774 }
775 }
776
85007c04
DB
777 struct tms tms_after;
778 times (& tms_after);
779 unsigned _sc_clk_tck = sysconf (_SC_CLK_TCK);
780 struct timeval tv_after;
781 gettimeofday (&tv_after, NULL);
782
783#define TIMESPRINT "in " << \
784 (tms_after.tms_cutime + tms_after.tms_utime \
785 - tms_before.tms_cutime - tms_before.tms_utime) * 1000 / (_sc_clk_tck) << "usr/" \
786 << (tms_after.tms_cstime + tms_after.tms_stime \
787 - tms_before.tms_cstime - tms_before.tms_stime) * 1000 / (_sc_clk_tck) << "sys/" \
788 << ((tv_after.tv_sec - tv_before.tv_sec) * 1000 + \
789 ((long)tv_after.tv_usec - (long)tv_before.tv_usec) / 1000) << "real ms."
790
791 // syntax errors, if any, are already printed
792 if (s.verbose)
793 {
e7c60c35 794 // XXX also include a count of helper macro files loaded (.stpm)?
85007c04
DB
795 clog << "Pass 1: parsed user script and "
796 << s.library_files.size()
797 << " library script(s) "
798 << getmemusage()
799 << TIMESPRINT
800 << endl;
801 }
802
bba368c5 803 if (rc && !s.dump_mode)
1f35f4db 804 cerr << _("Pass 1: parse failed. [man error::pass1]") << endl;
85007c04 805
0f5d597d 806 PROBE1(stap, pass1__end, &s);
85007c04 807
e19ebcf7 808 assert_no_interrupts();
bba368c5
JL
809 if (rc || s.last_pass == 1 ||
810 s.dump_mode == systemtap_session::dump_probe_aliases)
811 return rc;
85007c04
DB
812
813 times (& tms_before);
814 gettimeofday (&tv_before, NULL);
815
816 // PASS 2: ELABORATION
817 s.verbose = s.perpass_verbose[1];
0f5d597d 818 PROBE1(stap, pass2__start, &s);
85007c04
DB
819 rc = semantic_pass (s);
820
b82d77b4 821 // Dump a list of known probe point types, if requested.
bba368c5 822 if (s.dump_mode == systemtap_session::dump_probe_types)
b82d77b4 823 s.pattern_root->dump (s);
eb9ea966 824 // Dump a list of functions we picked up, if requested.
bba368c5 825 else if (s.dump_mode == systemtap_session::dump_functions)
eb9ea966
JL
826 {
827 map<string,functiondecl*>::const_iterator func;
828 for (func = s.functions.begin();
829 func != s.functions.end(); ++func)
830 {
831 functiondecl& curfunc = *func->second;
832 if (curfunc.synthetic)
833 continue;
834 if (!s.verbose && startswith(curfunc.name, "_"))
835 continue;
836 curfunc.printsigtags(cout, s.verbose>0 /* all_tags */ );
837 cout << endl;
838 }
839 }
840 // Dump the whole script if requested, or if we stop at 2
bba368c5
JL
841 else if (s.dump_mode == systemtap_session::dump_matched_probes ||
842 s.dump_mode == systemtap_session::dump_matched_probes_vars ||
843 (rc == 0 && s.last_pass == 2))
85007c04
DB
844 printscript(s, cout);
845
846 times (& tms_after);
847 gettimeofday (&tv_after, NULL);
848
849 if (s.verbose) clog << "Pass 2: analyzed script: "
850 << s.probes.size() << " probe(s), "
851 << s.functions.size() << " function(s), "
852 << s.embeds.size() << " embed(s), "
853 << s.globals.size() << " global(s) "
854 << getmemusage()
855 << TIMESPRINT
856 << endl;
857
bba368c5 858 if (rc && !s.dump_mode && !s.try_server ())
1f35f4db 859 cerr << _("Pass 2: analysis failed. [man error::pass2]") << endl;
85007c04 860
0f5d597d 861 PROBE1(stap, pass2__end, &s);
85007c04 862
e19ebcf7 863 assert_no_interrupts();
bba368c5
JL
864 // NB: none of the dump modes need to go beyond pass-2. If this changes, break
865 // into individual modes here.
866 if (rc || s.last_pass == 2 || s.dump_mode)
867 return rc;
85007c04 868
d13bcfd8 869 rc = prepare_translate_pass (s);
e19ebcf7 870 assert_no_interrupts();
985892de 871 if (rc) return rc;
d13bcfd8 872
85007c04
DB
873 // Generate hash. There isn't any point in generating the hash
874 // if last_pass is 2, since we'll quit before using it.
875 if (s.use_script_cache)
876 {
877 ostringstream o;
878 unsigned saved_verbose;
879
880 {
881 // Make sure we're in verbose mode, so that printscript()
882 // will output function/probe bodies.
883 saved_verbose = s.verbose;
884 s.verbose = 3;
885 printscript(s, o); // Print script to 'o'
886 s.verbose = saved_verbose;
887 }
888
889 // Generate hash
890 find_script_hash (s, o.str());
891
892 // See if we can use cached source/module.
893 if (get_script_from_cache(s))
894 {
7d26ee02
JS
895 // We may still need to build uprobes, if it's not also cached.
896 if (s.need_uprobes)
897 rc = uprobes_pass(s);
898
85007c04
DB
899 // If our last pass isn't 5, we're done (since passes 3 and
900 // 4 just generate what we just pulled out of the cache).
e19ebcf7 901 assert_no_interrupts();
985892de 902 if (rc || s.last_pass < 5) return rc;
85007c04
DB
903
904 // Short-circuit to pass 5.
905 return 0;
906 }
907 }
908
909 // PASS 3: TRANSLATION
910 s.verbose = s.perpass_verbose[2];
911 times (& tms_before);
912 gettimeofday (&tv_before, NULL);
0f5d597d 913 PROBE1(stap, pass3__start, &s);
85007c04
DB
914
915 rc = translate_pass (s);
3e1ec884 916 if (! rc && s.last_pass == 3)
85007c04
DB
917 {
918 ifstream i (s.translated_source.c_str());
919 cout << i.rdbuf();
920 }
921
922 times (& tms_after);
923 gettimeofday (&tv_after, NULL);
924
79bc39ab
LB
925 if (s.verbose)
926 clog << "Pass 3: translated to C into \""
927 << s.translated_source
928 << "\" "
929 << getmemusage()
930 << TIMESPRINT
85007c04
DB
931 << endl;
932
44edbcd6 933 if (rc && ! s.try_server ())
1f35f4db 934 cerr << _("Pass 3: translation failed. [man error::pass3]") << endl;
79bc39ab 935
0f5d597d 936 PROBE1(stap, pass3__end, &s);
85007c04 937
e19ebcf7 938 assert_no_interrupts();
985892de 939 if (rc || s.last_pass == 3) return rc;
85007c04
DB
940
941 // PASS 4: COMPILATION
942 s.verbose = s.perpass_verbose[3];
943 times (& tms_before);
944 gettimeofday (&tv_before, NULL);
0f5d597d 945 PROBE1(stap, pass4__start, &s);
85007c04
DB
946
947 if (s.use_cache)
948 {
949 find_stapconf_hash(s);
950 get_stapconf_from_cache(s);
951 }
952 rc = compile_pass (s);
3e1ec884 953 if (! rc && s.last_pass == 4)
85007c04 954 {
4441e344 955 cout << ((s.hash_path == "") ? s.module_filename() : s.hash_path);
85007c04
DB
956 cout << endl;
957 }
958
959 times (& tms_after);
960 gettimeofday (&tv_after, NULL);
961
962 if (s.verbose) clog << "Pass 4: compiled C into \""
4441e344 963 << s.module_filename()
85007c04
DB
964 << "\" "
965 << TIMESPRINT
966 << endl;
967
44edbcd6 968 if (rc && ! s.try_server ())
1f35f4db 969 cerr << _("Pass 4: compilation failed. [man error::pass4]") << endl;
be4b2eed 970
85007c04
DB
971 else
972 {
973 // Update cache. Cache cleaning is kicked off at the beginning of this function.
974 if (s.use_script_cache)
975 add_script_to_cache(s);
ac3af990 976 if (s.use_cache && !s.runtime_usermode_p())
85007c04
DB
977 add_stapconf_to_cache(s);
978
979 // We may need to save the module in $CWD if the cache was
980 // inaccessible for some reason.
981 if (! s.use_script_cache && s.last_pass == 4)
982 s.save_module = true;
983
984 // Copy module to the current directory.
985 if (s.save_module && !pending_interrupts)
986 {
4441e344
JS
987 string module_src_path = s.tmpdir + "/" + s.module_filename();
988 string module_dest_path = s.module_filename();
85007c04
DB
989 copy_file(module_src_path, module_dest_path, s.verbose > 1);
990 }
50f92d4e
SH
991
992 // Copy uprobes module to the current directory.
91ea0ce6 993 if (s.save_uprobes && !s.uprobes_path.empty() && !pending_interrupts)
50f92d4e
SH
994 {
995 rc = create_dir("uprobes");
996 if (! rc)
997 copy_file(s.uprobes_path, "uprobes/uprobes.ko", s.verbose > 1);
998 }
85007c04
DB
999 }
1000
0f5d597d 1001 PROBE1(stap, pass4__end, &s);
85007c04
DB
1002
1003 return rc;
1004}
1005
1006static int
ebff2ed0 1007pass_5 (systemtap_session &s, vector<remote*> targets)
85007c04
DB
1008{
1009 // PASS 5: RUN
1010 s.verbose = s.perpass_verbose[4];
1011 struct tms tms_before;
1012 times (& tms_before);
1013 struct timeval tv_before;
1014 gettimeofday (&tv_before, NULL);
1015 // NB: this message is a judgement call. The other passes don't emit
1016 // a "hello, I'm starting" message, but then the others aren't interactive
1017 // and don't take an indefinite amount of time.
0f5d597d 1018 PROBE1(stap, pass5__start, &s);
79bc39ab 1019 if (s.verbose) clog << _("Pass 5: starting run.") << endl;
4f244435 1020 int rc = remote::run(targets);
85007c04
DB
1021 struct tms tms_after;
1022 times (& tms_after);
1023 unsigned _sc_clk_tck = sysconf (_SC_CLK_TCK);
1024 struct timeval tv_after;
1025 gettimeofday (&tv_after, NULL);
1026 if (s.verbose) clog << "Pass 5: run completed "
1027 << TIMESPRINT
1028 << endl;
1029
1030 if (rc)
1f35f4db 1031 cerr << _("Pass 5: run failed. [man error::pass5]") << endl;
85007c04
DB
1032 else
1033 // Interrupting pass-5 to quit is normal, so we want an EXIT_SUCCESS below.
1034 pending_interrupts = 0;
1035
0f5d597d 1036 PROBE1(stap, pass5__end, &s);
85007c04
DB
1037
1038 return rc;
1039}
1040
1041static void
1042cleanup (systemtap_session &s, int rc)
1043{
1044 // PASS 6: cleaning up
0f5d597d 1045 PROBE1(stap, pass6__start, &s);
85007c04 1046
ebff2ed0
JS
1047 for (systemtap_session::session_map_t::iterator it = s.subsessions.begin();
1048 it != s.subsessions.end(); ++it)
1049 cleanup (*it->second, rc);
1050
85007c04
DB
1051 // update the database information
1052 if (!rc && s.tapset_compile_coverage && !pending_interrupts) {
1053#ifdef HAVE_LIBSQLITE3
1054 update_coverage_db(s);
1055#else
79bc39ab 1056 cerr << _("Coverage database not available without libsqlite3") << endl;
85007c04
DB
1057#endif
1058 }
1059
678b7381 1060 s.report_suppression();
9e1a2390 1061
0f5d597d 1062 PROBE1(stap, pass6__end, &s);
85007c04
DB
1063}
1064
44edbcd6
JS
1065static int
1066passes_0_4_again_with_server (systemtap_session &s)
1067{
1068 // Not a server and not already using a server.
1069 assert (! s.client_options);
1070 assert (s.specified_servers.empty ());
1071
1072 // Specify default server(s).
1073 s.specified_servers.push_back ("");
1074
b96901b7
CM
1075 // Reset the previous temporary directory and start fresh
1076 s.reset_tmp_dir();
44edbcd6
JS
1077
1078 // Try to compile again, using the server
b5f561be 1079 clog << _("Attempting compilation using a compile server")
44edbcd6 1080 << endl;
b96901b7 1081
44edbcd6
JS
1082 int rc = passes_0_4 (s);
1083 return rc;
1084}
1085
85007c04
DB
1086int
1087main (int argc, char * const argv [])
1088{
1089 // Initialize defaults.
b96901b7 1090 try {
891043f0 1091 systemtap_session s;
52c2652f 1092#if ENABLE_NLS
891043f0
CM
1093 setlocale (LC_ALL, "");
1094 bindtextdomain (PACKAGE, LOCALEDIR);
1095 textdomain (PACKAGE);
52c2652f 1096#endif
891043f0
CM
1097
1098 // Set up our handler to catch routine signals, to allow clean
1099 // and reasonably timely exit.
1100 setup_signals(&handle_interrupt);
1101
1102 // PR13520: Parse $SYSTEMTAP_DIR/rc for extra options
1103 string rc_file = s.data_path + "/rc";
1104 ifstream rcf (rc_file.c_str());
1105 string rcline;
1106 wordexp_t words;
1107 memset (& words, 0, sizeof(words));
1108 int rc = 0;
1109 int linecount = 0;
1110 while (getline (rcf, rcline))
1111 {
1112 rc = wordexp (rcline.c_str(), & words, WRDE_NOCMD|WRDE_UNDEF|
1113 (linecount > 0 ? WRDE_APPEND : 0));
1114 // NB: WRDE_APPEND automagically reallocates words.* as more options are added.
1115 linecount ++;
1116 if (rc) break;
1117 }
1118 int extended_argc = words.we_wordc + argc;
1119 char **extended_argv = (char**) calloc (extended_argc + 1, sizeof(char*));
1120 if (rc || !extended_argv)
1121 {
1122 clog << _F("Error processing extra options in %s", rc_file.c_str());
e2d0f787 1123 return EXIT_FAILURE;
891043f0
CM
1124 }
1125 // Copy over the arguments *by reference*, first the ones from the rc file.
1126 char **p = & extended_argv[0];
1127 *p++ = argv[0];
1128 for (unsigned i=0; i<words.we_wordc; i++) *p++ = words.we_wordv[i];
1129 for (int j=1; j<argc; j++) *p++ = argv[j];
1130 *p++ = NULL;
1131
1132 // Process the command line.
1133 rc = s.parse_cmdline (extended_argc, extended_argv);
1134 if (rc != 0)
e2d0f787 1135 return rc;
891043f0
CM
1136
1137 if (words.we_wordc > 0 && s.verbose > 1)
1138 clog << _F("Extra options in %s: %d\n", rc_file.c_str(), (int)words.we_wordc);
1139
1140 // Check for options conflicts. Exits if errors are detected.
1141 s.check_options (extended_argc, extended_argv);
1142
1143 // We don't need these strings any more.
1144 wordfree (& words);
1145 free (extended_argv);
1146
1147 // arguments parsed; get down to business
1148 if (s.verbose > 1)
1149 s.version ();
1150
1151 // Need to send the verbose message here, rather than in the session ctor, since
1152 // we didn't know if verbose was set.
1153 if (rc == 0 && s.verbose>1)
1154 clog << _F("Created temporary directory \"%s\"", s.tmpdir.c_str()) << endl;
1155
3d0a328d
JS
1156 // Run the benchmark and quit right away.
1157 if (s.benchmark_sdt_loops || s.benchmark_sdt_threads)
1158 return run_sdt_benchmark(s);
1159
891043f0
CM
1160 // Prepare connections for each specified remote target.
1161 vector<remote*> targets;
1162 bool fake_remote=false;
1163 if (s.remote_uris.empty())
1164 {
1165 fake_remote=true;
1166 s.remote_uris.push_back("direct:");
1167 }
1168 for (unsigned i = 0; rc == 0 && i < s.remote_uris.size(); ++i)
1169 {
1170 // PR13354: pass remote id#/url only in non --remote=HOST cases
1171 remote *target = remote::create(s, s.remote_uris[i],
1172 fake_remote ? -1 : (int)i);
1173 if (target)
1174 targets.push_back(target);
1175 else
1176 rc = 1;
1177 }
3a97e514 1178
891043f0
CM
1179 // Discover and loop over each unique session created by the remote targets.
1180 set<systemtap_session*> sessions;
1181 for (unsigned i = 0; i < targets.size(); ++i)
1182 sessions.insert(targets[i]->get_session());
1183 for (set<systemtap_session*>::iterator it = sessions.begin();
1184 rc == 0 && !pending_interrupts && it != sessions.end(); ++it)
1185 {
1186 systemtap_session& ss = **it;
1187 if (ss.verbose > 1)
1188 clog << _F("Session arch: %s release: %s",
1189 ss.architecture.c_str(), ss.kernel_release.c_str()) << endl;
85007c04 1190
c4fd15b4 1191#if HAVE_NSS
891043f0
CM
1192 // If requested, query server status. This is independent of other tasks.
1193 query_server_status (ss);
85007c04 1194
891043f0
CM
1195 // If requested, manage trust of servers. This is independent of other tasks.
1196 manage_server_trust (ss);
c4fd15b4 1197#endif
ebff2ed0 1198
bba368c5
JL
1199 // Run the passes only if a script has been specified or if we're
1200 // dumping something. The requirement for a script has already been
1201 // checked in systemtap_session::check_options.
1202 if (ss.have_script || ss.dump_mode)
891043f0
CM
1203 {
1204 // Run passes 0-4 for each unique session,
1205 // either locally or using a compile-server.
1206 ss.init_try_server ();
1207 if ((rc = passes_0_4 (ss)))
1208 {
1209 // Compilation failed.
1210 // Try again using a server if appropriate.
1211 if (ss.try_server ())
1212 rc = passes_0_4_again_with_server (ss);
1213 }
4e78c716
DB
1214 if (rc || s.perpass_verbose[0] >= 1)
1215 s.explain_auto_options ();
891043f0 1216 }
891043f0 1217 }
3a97e514 1218
891043f0
CM
1219 // Run pass 5, if requested
1220 if (rc == 0 && s.have_script && s.last_pass >= 5 && ! pending_interrupts)
1221 rc = pass_5 (s, targets);
85007c04 1222
891043f0
CM
1223 // Pass 6. Cleanup
1224 for (unsigned i = 0; i < targets.size(); ++i)
1225 delete targets[i];
1226 cleanup (s, rc);
b96901b7 1227
e19ebcf7 1228 assert_no_interrupts();
985892de 1229 return (rc) ? EXIT_FAILURE : EXIT_SUCCESS;
b96901b7 1230 }
8d4072eb 1231 catch (const interrupt_exception& e) {
985892de 1232 // User entered ctrl-c, exit quietly.
e2d0f787
JS
1233 return EXIT_FAILURE;
1234 }
1235 catch (const exit_exception& e) {
1236 // Exiting for any quiet reason.
1237 return e.rc;
985892de 1238 }
29375627
JL
1239 catch (const exception &e) {
1240 // Some other uncaught exception.
985892de 1241 cerr << e.what() << endl;
e2d0f787 1242 return EXIT_FAILURE;
985892de
CM
1243 }
1244 catch (...) {
1245 // Catch all other unknown exceptions.
1246 cerr << _("ERROR: caught unknown exception!") << endl;
e2d0f787 1247 return EXIT_FAILURE;
b96901b7 1248 }
85007c04
DB
1249}
1250
1251/* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
This page took 0.343396 seconds and 5 git commands to generate.