1 // systemtap translator/driver
2 // Copyright (C) 2005-2011 Red Hat Inc.
3 // Copyright (C) 2005 IBM Corp.
4 // Copyright (C) 2006 Intel Corporation.
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
14 #include "elaborate.h"
15 #include "translate.h"
21 #include "coveragedb.h"
22 #include "rpm_finder.h"
23 #include "task_finder.h"
31 #include "stap-probe.h"
39 #include <sys/utsname.h>
40 #include <sys/times.h>
51 uniq_list(list
<string
>& l
)
54 list
<string
>::iterator i
= l
.begin();
56 if (s
.insert(*i
).second
)
63 printscript(systemtap_session
& s
, ostream
& o
)
67 // We go through some heroic measures to produce clean output.
68 // Record the alias and probe pointer as <name, set<derived_probe *> >
69 map
<string
,set
<derived_probe
*> > probe_list
;
71 // Pre-process the probe alias
72 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
74 if (pending_interrupts
) return;
76 derived_probe
* p
= s
.probes
[i
];
77 // NB: p->basest() is not so interesting;
78 // p->almost_basest() doesn't quite work, so ...
80 p
->collect_derivation_chain (chain
);
81 probe
* second
= (chain
.size()>1) ? chain
[chain
.size()-2] : chain
[0];
84 p
->printsig(cerr
); cerr
<< endl
;
85 cerr
<< "chain[" << chain
.size() << "]:" << endl
;
86 for (unsigned j
=0; j
<chain
.size(); j
++)
88 cerr
<< " [" << j
<< "]: " << endl
;
89 cerr
<< "\tlocations[" << chain
[j
]->locations
.size() << "]:" << endl
;
90 for (unsigned k
=0; k
<chain
[j
]->locations
.size(); k
++)
92 cerr
<< "\t [" << k
<< "]: ";
93 chain
[j
]->locations
[k
]->print(cerr
);
96 const probe_alias
*a
= chain
[j
]->get_alias();
99 cerr
<< "\taliases[" << a
->alias_names
.size() << "]:" << endl
;
100 for (unsigned k
=0; k
<a
->alias_names
.size(); k
++)
102 cerr
<< "\t [" << k
<< "]: ";
103 a
->alias_names
[k
]->print(cerr
);
111 const probe_alias
*a
= second
->get_alias();
114 assert (a
->alias_names
.size() >= 1);
115 a
->alias_names
[0]->print(tmps
); // XXX: [0] is arbitrary; perhaps print all
119 assert (second
->locations
.size() >= 1);
120 second
->locations
[0]->print(tmps
); // XXX: [0] is less arbitrary here, but still ...
122 string pp
= tmps
.str();
124 // Now duplicate-eliminate. An alias may have expanded to
125 // several actual derived probe points, but we only want to
126 // print the alias head name once.
127 probe_list
[pp
].insert(p
);
130 // print probe name and variables if there
131 for (map
<string
, set
<derived_probe
*> >::iterator it
=probe_list
.begin(); it
!=probe_list
.end(); ++it
)
133 o
<< it
->first
; // probe name or alias
135 // Print the locals and arguments for -L mode only
136 if (s
.listing_mode_vars
)
138 map
<string
,unsigned> var_count
; // format <"name:type",count>
139 map
<string
,unsigned> arg_count
;
140 list
<string
> var_list
;
141 list
<string
> arg_list
;
142 // traverse set<derived_probe *> to collect all locals and arguments
143 for (set
<derived_probe
*>::iterator ix
=it
->second
.begin(); ix
!=it
->second
.end(); ++ix
)
145 derived_probe
* p
= *ix
;
146 // collect available locals of the probe
147 for (unsigned j
=0; j
<p
->locals
.size(); j
++)
150 vardecl
* v
= p
->locals
[j
];
152 var_count
[tmps
.str()]++;
153 var_list
.push_back(tmps
.str());
155 // collect arguments of the probe if there
156 list
<string
> arg_set
;
158 for (list
<string
>::iterator ia
=arg_set
.begin(); ia
!=arg_set
.end(); ++ia
) {
160 arg_list
.push_back(*ia
);
167 // print the set-intersection only
168 for (list
<string
>::iterator ir
=var_list
.begin(); ir
!=var_list
.end(); ++ir
)
169 if (var_count
.find(*ir
)->second
== it
->second
.size()) // print locals
171 for (list
<string
>::iterator ir
=arg_list
.begin(); ir
!=arg_list
.end(); ++ir
)
172 if (arg_count
.find(*ir
)->second
== it
->second
.size()) // print arguments
180 if (s
.embeds
.size() > 0)
181 o
<< _("# global embedded code") << endl
;
182 for (unsigned i
=0; i
<s
.embeds
.size(); i
++)
184 if (pending_interrupts
) return;
185 embeddedcode
* ec
= s
.embeds
[i
];
190 if (s
.globals
.size() > 0)
191 o
<< _("# globals") << endl
;
192 for (unsigned i
=0; i
<s
.globals
.size(); i
++)
194 if (pending_interrupts
) return;
195 vardecl
* v
= s
.globals
[i
];
197 if (s
.verbose
&& v
->init
)
205 if (s
.functions
.size() > 0)
206 o
<< _("# functions") << endl
;
207 for (map
<string
,functiondecl
*>::iterator it
= s
.functions
.begin(); it
!= s
.functions
.end(); it
++)
209 if (pending_interrupts
) return;
210 functiondecl
* f
= it
->second
;
213 if (f
->locals
.size() > 0)
214 o
<< _(" # locals") << endl
;
215 for (unsigned j
=0; j
<f
->locals
.size(); j
++)
217 vardecl
* v
= f
->locals
[j
];
229 if (s
.probes
.size() > 0)
230 o
<< _("# probes") << endl
;
231 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
233 if (pending_interrupts
) return;
234 derived_probe
* p
= s
.probes
[i
];
237 if (p
->locals
.size() > 0)
238 o
<< _(" # locals") << endl
;
239 for (unsigned j
=0; j
<p
->locals
.size(); j
++)
241 vardecl
* v
= p
->locals
[j
];
256 int pending_interrupts
;
259 void handle_interrupt (int sig
)
261 // This might be nice, but we don't know our current verbosity...
262 // clog << _F("Received signal %d", sig) << endl << flush;
263 kill_stap_spawn(SIGTERM
);
265 pending_interrupts
++;
266 // Absorb the first two signals. This used to be one, but when
267 // stap is run under sudo, and then interrupted, sudo relays a
268 // redundant copy of the signal to stap, leading to an unclean shutdown.
269 if (pending_interrupts
> 2) // XXX: should be configurable? time-based?
271 char msg
[] = "Too many interrupts received, exiting.\n";
272 int rc
= write (2, msg
, sizeof(msg
)-1);
273 if (rc
) {/* Do nothing; we don't care if our last gasp went out. */ ;}
280 setup_signals (sighandler_t handler
)
284 memset(&sa
, 0, sizeof(sa
));
285 sa
.sa_handler
= handler
;
286 sigemptyset (&sa
.sa_mask
);
287 if (handler
!= SIG_IGN
)
289 sigaddset (&sa
.sa_mask
, SIGHUP
);
290 sigaddset (&sa
.sa_mask
, SIGPIPE
);
291 sigaddset (&sa
.sa_mask
, SIGINT
);
292 sigaddset (&sa
.sa_mask
, SIGTERM
);
293 sigaddset (&sa
.sa_mask
, SIGXFSZ
);
294 sigaddset (&sa
.sa_mask
, SIGXCPU
);
296 sa
.sa_flags
= SA_RESTART
;
298 sigaction (SIGHUP
, &sa
, NULL
);
299 sigaction (SIGPIPE
, &sa
, NULL
);
300 sigaction (SIGINT
, &sa
, NULL
);
301 sigaction (SIGTERM
, &sa
, NULL
);
302 sigaction (SIGXFSZ
, &sa
, NULL
);
303 sigaction (SIGXCPU
, &sa
, NULL
);
306 int parse_kernel_config (systemtap_session
&s
)
308 // PR10702: pull config options
309 string kernel_config_file
= s
.kernel_build_tree
+ "/.config";
311 int rc
= stat(kernel_config_file
.c_str(), &st
);
314 clog
<< _F("Checking \"%s\" failed with error: %s",
315 kernel_config_file
.c_str(), strerror(errno
)) << endl
;
316 find_devel_rpms(s
, s
.kernel_build_tree
.c_str());
317 missing_rpm_list_print(s
,"-devel");
321 ifstream
kcf (kernel_config_file
.c_str());
323 while (getline (kcf
, line
))
325 if (!startswith(line
, "CONFIG_")) continue;
326 size_t off
= line
.find('=');
327 if (off
== string::npos
) continue;
328 string key
= line
.substr(0, off
);
329 string value
= line
.substr(off
+1, string::npos
);
330 s
.kernel_config
[key
] = value
;
333 clog
<< _F("Parsed kernel \"%s\", ", kernel_config_file
.c_str())
334 << _F(ngettext("containing %zu tuple", "containing %zu tuples",
335 s
.kernel_config
.size()), s
.kernel_config
.size()) << endl
;
342 int parse_kernel_exports (systemtap_session
&s
)
344 string kernel_exports_file
= s
.kernel_build_tree
+ "/Module.symvers";
346 int rc
= stat(kernel_exports_file
.c_str(), &st
);
349 clog
<< _F("Checking \"%s\" failed with error: %s\nEnsure kernel development headers & makefiles are installed",
350 kernel_exports_file
.c_str(), strerror(errno
)) << endl
;
354 ifstream
kef (kernel_exports_file
.c_str());
356 while (getline (kef
, line
))
358 vector
<string
> tokens
;
359 tokenize (line
, tokens
, "\t");
360 if (tokens
.size() == 4 &&
361 tokens
[2] == "vmlinux" &&
362 tokens
[3].substr(0,13) == string("EXPORT_SYMBOL"))
363 s
.kernel_exports
.insert (tokens
[1]);
364 // RHEL4 Module.symvers file only has 3 tokens. No
365 // 'EXPORT_SYMBOL' token at the end of the line.
366 else if (tokens
.size() == 3 && tokens
[2] == "vmlinux")
367 s
.kernel_exports
.insert (tokens
[1]);
370 clog
<< _F(ngettext("Parsed kernel %s, which contained one vmlinux export",
371 "Parsed kernel %s, which contained %zu vmlinux exports",
372 s
.kernel_exports
.size()), kernel_exports_file
.c_str(),
373 s
.kernel_exports
.size()) << endl
;
381 create_temp_dir (systemtap_session
&s
)
383 if (!s
.tmpdir
.empty())
386 // Create a temporary directory to build within.
387 // Be careful with this, as "tmpdir" is "rm -rf"'d at the end.
388 const char * tmpdir_env
= getenv("TMPDIR");
392 string stapdir
= "/stapXXXXXX";
393 string tmpdirt
= tmpdir_env
+ stapdir
;
394 const char *tmpdir_name
= mkdtemp((char *)tmpdirt
.c_str());
397 const char* e
= strerror(errno
);
398 //TRANSLATORS: we can't make the directory due to the error
399 cerr
<< _F("ERROR: cannot create temporary directory (\" %s \"): %s", tmpdirt
.c_str(), e
) << endl
;
403 s
.tmpdir
= tmpdir_name
;
406 clog
<< _F("Created temporary directory \"%s\"", s
.tmpdir
.c_str()) << endl
;
411 remove_temp_dir(systemtap_session
&s
)
413 if (!s
.tmpdir
.empty())
415 if (s
.keep_tmpdir
&& !s
.tmpdir_opt_set
)
416 clog
<< _F("Keeping temporary directory \"%s\"", s
.tmpdir
.c_str()) << endl
;
417 else if (!s
.tmpdir_opt_set
)
419 // Mask signals while we're deleting the temporary directory.
420 stap_sigmasker masked
;
422 // Remove the temporary directory.
423 vector
<string
> cleanupcmd
;
424 cleanupcmd
.push_back("rm");
425 cleanupcmd
.push_back("-rf");
426 cleanupcmd
.push_back(s
.tmpdir
);
428 (void) stap_system(s
.verbose
, cleanupcmd
);
434 // Compilation passes 0 through 4
436 passes_0_4 (systemtap_session
&s
)
440 // If we don't know the release, there's no hope either locally or on a server.
441 if (s
.kernel_release
.empty())
443 if (s
.kernel_build_tree
.empty())
444 cerr
<< _("ERROR: kernel release isn't specified") << endl
;
446 cerr
<< _F("ERROR: kernel release isn't found in \"%s\"",
447 s
.kernel_build_tree
.c_str()) << endl
;
451 // Create a temporary directory to build within.
452 // Be careful with this, as "s.tmpdir" is "rm -rf"'d at the end.
453 rc
= create_temp_dir (s
);
457 // Perform passes 0 through 4 using a compile server?
458 if (! s
.specified_servers
.empty ())
461 compile_server_client
client (s
);
462 int rc
= client
.passes_0_4 ();
463 // Need to give a user a better diagnostic, if she didn't
464 // even ask for a server
465 if (rc
&& s
.automatic_server_mode
) {
466 cerr
<< _("Note: --use-server --unprivileged was selected because of stapusr membership.") << endl
;
470 s
.print_warning("Without NSS, using a compile-server is not supported by this version of systemtap");
471 // This cannot be an attempt to use a server after a local compile failed
472 // since --use-server-on-error is locked to 'no' if we don't have
474 assert (! s
.try_server ());
478 // PASS 0: setting up
479 s
.verbose
= s
.perpass_verbose
[0];
480 PROBE1(stap
, pass0__start
, &s
);
482 // For PR1477, we used to override $PATH and $LC_ALL and other stuff
483 // here. We seem to use complete pathnames in
484 // buildrun.cxx/tapsets.cxx now, so this is not necessary. Further,
485 // it interferes with util.cxx:find_executable(), used for $PATH
488 s
.kernel_base_release
.assign(s
.kernel_release
, 0, s
.kernel_release
.find('-'));
490 // Now that no further changes to s.kernel_build_tree can occur, let's use it.
491 if ((rc
= parse_kernel_config (s
)) != 0)
493 // Try again with a server
498 if ((rc
= parse_kernel_exports (s
)) != 0)
500 // Try again with a server
505 // Create the name of the C source file within the temporary
506 // directory. Note the _src prefix, explained in
507 // buildrun.cxx:compile_pass()
508 s
.translated_source
= string(s
.tmpdir
) + "/" + s
.module_name
+ "_src.c";
510 PROBE1(stap
, pass0__end
, &s
);
512 struct tms tms_before
;
513 times (& tms_before
);
514 struct timeval tv_before
;
515 gettimeofday (&tv_before
, NULL
);
517 // PASS 1a: PARSING USER SCRIPT
518 PROBE1(stap
, pass1a__start
, &s
);
520 struct stat user_file_stat
;
521 int user_file_stat_rc
= -1;
523 if (s
.script_file
== "-")
525 s
.user_file
= parse (s
, cin
, s
.guru_mode
);
526 user_file_stat_rc
= fstat (STDIN_FILENO
, & user_file_stat
);
528 else if (s
.script_file
!= "")
530 s
.user_file
= parse (s
, s
.script_file
, s
.guru_mode
);
531 user_file_stat_rc
= stat (s
.script_file
.c_str(), & user_file_stat
);
535 istringstream
ii (s
.cmdline_script
);
536 s
.user_file
= parse (s
, ii
, s
.guru_mode
);
538 if (s
.user_file
== 0)
540 // Syntax errors already printed.
544 // Construct arch / kernel-versioning search path
545 vector
<string
> version_suffixes
;
546 string kvr
= s
.kernel_release
;
547 const string
& arch
= s
.architecture
;
548 // add full kernel-version-release (2.6.NN-FOOBAR) + arch
549 version_suffixes
.push_back ("/" + kvr
+ "/" + arch
);
550 version_suffixes
.push_back ("/" + kvr
);
551 // add kernel version (2.6.NN) + arch
552 if (kvr
!= s
.kernel_base_release
) {
553 kvr
= s
.kernel_base_release
;
554 version_suffixes
.push_back ("/" + kvr
+ "/" + arch
);
555 version_suffixes
.push_back ("/" + kvr
);
557 // add kernel family (2.6) + arch
558 string::size_type dot1_index
= kvr
.find ('.');
559 string::size_type dot2_index
= kvr
.rfind ('.');
560 while (dot2_index
> dot1_index
&& dot2_index
!= string::npos
) {
561 kvr
.erase(dot2_index
);
562 version_suffixes
.push_back ("/" + kvr
+ "/" + arch
);
563 version_suffixes
.push_back ("/" + kvr
);
564 dot2_index
= kvr
.rfind ('.');
566 // add architecture search path
567 version_suffixes
.push_back("/" + arch
);
568 // add empty string as last element
569 version_suffixes
.push_back ("");
571 // PASS 1b: PARSING LIBRARY SCRIPTS
572 PROBE1(stap
, pass1b__start
, &s
);
574 set
<pair
<dev_t
, ino_t
> > seen_library_files
;
576 for (unsigned i
=0; i
<s
.include_path
.size(); i
++)
578 // now iterate upon it
579 for (unsigned k
=0; k
<version_suffixes
.size(); k
++)
582 string dir
= s
.include_path
[i
] + version_suffixes
[k
] + "/*.stp";
583 int r
= glob(dir
.c_str (), 0, NULL
, & globbuf
);
584 if (r
== GLOB_NOSPACE
|| r
== GLOB_ABORTED
)
586 // GLOB_NOMATCH is acceptable
588 unsigned prev_s_library_files
= s
.library_files
.size();
590 for (unsigned j
=0; j
<globbuf
.gl_pathc
; j
++)
592 if (pending_interrupts
)
595 struct stat tapset_file_stat
;
596 int stat_rc
= stat (globbuf
.gl_pathv
[j
], & tapset_file_stat
);
597 if (stat_rc
== 0 && user_file_stat_rc
== 0 &&
598 user_file_stat
.st_dev
== tapset_file_stat
.st_dev
&&
599 user_file_stat
.st_ino
== tapset_file_stat
.st_ino
)
602 << _F("usage error: tapset file '%s' cannot be run directly as a session script.",
603 globbuf
.gl_pathv
[j
]) << endl
;
607 // PR11949: duplicate-eliminate tapset files
610 pair
<dev_t
,ino_t
> here
= make_pair(tapset_file_stat
.st_dev
,
611 tapset_file_stat
.st_ino
);
612 if (seen_library_files
.find(here
) != seen_library_files
.end())
614 seen_library_files
.insert (here
);
617 // XXX: privilege only for /usr/share/systemtap?
618 stapfile
* f
= parse (s
, globbuf
.gl_pathv
[j
], true);
620 s
.print_warning("tapset '" + string(globbuf
.gl_pathv
[j
])
621 + "' has errors, and will be skipped.");
623 s
.library_files
.push_back (f
);
626 unsigned next_s_library_files
= s
.library_files
.size();
627 if (s
.verbose
>1 && globbuf
.gl_pathc
> 0)
628 //TRANSLATORS: Searching through directories, 'processed' means 'examined so far'
629 clog
<< _F("Searched: \" %s \", found: %zu, processed: %u",
630 dir
.c_str(), globbuf
.gl_pathc
,
631 (next_s_library_files
-prev_s_library_files
)) << endl
;
633 globfree (& globbuf
);
639 if (rc
== 0 && s
.last_pass
== 1)
641 cout
<< _("# parse tree dump") << endl
;
642 s
.user_file
->print (cout
);
645 for (unsigned i
=0; i
<s
.library_files
.size(); i
++)
647 s
.library_files
[i
]->print (cout
);
652 struct tms tms_after
;
654 unsigned _sc_clk_tck
= sysconf (_SC_CLK_TCK
);
655 struct timeval tv_after
;
656 gettimeofday (&tv_after
, NULL
);
658 #define TIMESPRINT "in " << \
659 (tms_after.tms_cutime + tms_after.tms_utime \
660 - tms_before.tms_cutime - tms_before.tms_utime) * 1000 / (_sc_clk_tck) << "usr/" \
661 << (tms_after.tms_cstime + tms_after.tms_stime \
662 - tms_before.tms_cstime - tms_before.tms_stime) * 1000 / (_sc_clk_tck) << "sys/" \
663 << ((tv_after.tv_sec - tv_before.tv_sec) * 1000 + \
664 ((long)tv_after.tv_usec - (long)tv_before.tv_usec) / 1000) << "real ms."
666 // syntax errors, if any, are already printed
669 clog
<< "Pass 1: parsed user script and "
670 << s
.library_files
.size()
671 << " library script(s) "
677 if (rc
&& !s
.listing_mode
)
678 cerr
<< _("Pass 1: parse failed. Try again with another '--vp 1' option.") << endl
;
679 //cerr << "Pass 1: parse failed. "
680 // << "Try again with another '--vp 1' option."
683 PROBE1(stap
, pass1__end
, &s
);
685 if (rc
|| s
.last_pass
== 1 || pending_interrupts
) return rc
;
687 times (& tms_before
);
688 gettimeofday (&tv_before
, NULL
);
690 // PASS 2: ELABORATION
691 s
.verbose
= s
.perpass_verbose
[1];
692 PROBE1(stap
, pass2__start
, &s
);
693 rc
= semantic_pass (s
);
695 // Dump a list of known probe point types, if requested.
696 if (s
.dump_probe_types
)
697 s
.pattern_root
->dump (s
);
699 if (s
.listing_mode
|| (rc
== 0 && s
.last_pass
== 2))
700 printscript(s
, cout
);
703 gettimeofday (&tv_after
, NULL
);
705 if (s
.verbose
) clog
<< "Pass 2: analyzed script: "
706 << s
.probes
.size() << " probe(s), "
707 << s
.functions
.size() << " function(s), "
708 << s
.embeds
.size() << " embed(s), "
709 << s
.globals
.size() << " global(s) "
714 if (rc
&& !s
.listing_mode
&& !s
.try_server ())
715 cerr
<< _("Pass 2: analysis failed. Try again with another '--vp 01' option.") << endl
;
716 //cerr << "Pass 2: analysis failed. "
717 // << "Try again with another '--vp 01' option."
720 /* Print out list of missing files. XXX should be "if (rc)" ? */
721 missing_rpm_list_print(s
,"-debuginfo");
723 PROBE1(stap
, pass2__end
, &s
);
725 if (rc
|| s
.listing_mode
|| s
.last_pass
== 2 || pending_interrupts
) return rc
;
727 rc
= prepare_translate_pass (s
);
728 if (rc
|| pending_interrupts
) return rc
;
730 // Generate hash. There isn't any point in generating the hash
731 // if last_pass is 2, since we'll quit before using it.
732 if (s
.use_script_cache
)
735 unsigned saved_verbose
;
738 // Make sure we're in verbose mode, so that printscript()
739 // will output function/probe bodies.
740 saved_verbose
= s
.verbose
;
742 printscript(s
, o
); // Print script to 'o'
743 s
.verbose
= saved_verbose
;
747 find_script_hash (s
, o
.str());
749 // See if we can use cached source/module.
750 if (get_script_from_cache(s
))
752 // We may still need to build uprobes, if it's not also cached.
754 rc
= uprobes_pass(s
);
756 // If our last pass isn't 5, we're done (since passes 3 and
757 // 4 just generate what we just pulled out of the cache).
758 if (rc
|| s
.last_pass
< 5 || pending_interrupts
)
761 // Short-circuit to pass 5.
766 // PASS 3: TRANSLATION
767 s
.verbose
= s
.perpass_verbose
[2];
768 times (& tms_before
);
769 gettimeofday (&tv_before
, NULL
);
770 PROBE1(stap
, pass3__start
, &s
);
772 rc
= translate_pass (s
);
773 if (! rc
&& s
.last_pass
== 3)
775 ifstream
i (s
.translated_source
.c_str());
780 gettimeofday (&tv_after
, NULL
);
783 clog
<< "Pass 3: translated to C into \""
784 << s
.translated_source
790 if (rc
&& ! s
.try_server ())
791 cerr
<< _("Pass 3: translation failed. Try again with another '--vp 001' option.") << endl
;
792 //cerr << "Pass 3: translation failed. "
793 // << "Try again with another '--vp 001' option."
796 PROBE1(stap
, pass3__end
, &s
);
798 if (rc
|| s
.last_pass
== 3 || pending_interrupts
) return rc
;
800 // PASS 4: COMPILATION
801 s
.verbose
= s
.perpass_verbose
[3];
802 times (& tms_before
);
803 gettimeofday (&tv_before
, NULL
);
804 PROBE1(stap
, pass4__start
, &s
);
808 find_stapconf_hash(s
);
809 get_stapconf_from_cache(s
);
811 rc
= compile_pass (s
);
812 if (! rc
&& s
.last_pass
== 4)
814 cout
<< ((s
.hash_path
== "") ? (s
.module_name
+ string(".ko")) : s
.hash_path
);
819 gettimeofday (&tv_after
, NULL
);
821 if (s
.verbose
) clog
<< "Pass 4: compiled C into \""
822 << s
.module_name
<< ".ko"
827 if (rc
&& ! s
.try_server ())
828 cerr
<< _("Pass 4: compilation failed. Try again with another '--vp 0001' option.") << endl
;
829 //cerr << "Pass 4: compilation failed. "
830 // << "Try again with another '--vp 0001' option."
834 // Update cache. Cache cleaning is kicked off at the beginning of this function.
835 if (s
.use_script_cache
)
836 add_script_to_cache(s
);
838 add_stapconf_to_cache(s
);
840 // We may need to save the module in $CWD if the cache was
841 // inaccessible for some reason.
842 if (! s
.use_script_cache
&& s
.last_pass
== 4)
843 s
.save_module
= true;
845 // Copy module to the current directory.
846 if (s
.save_module
&& !pending_interrupts
)
848 string module_src_path
= s
.tmpdir
+ "/" + s
.module_name
+ ".ko";
849 string module_dest_path
= s
.module_name
+ ".ko";
850 copy_file(module_src_path
, module_dest_path
, s
.verbose
> 1);
854 PROBE1(stap
, pass4__end
, &s
);
860 pass_5 (systemtap_session
&s
, vector
<remote
*> targets
)
863 s
.verbose
= s
.perpass_verbose
[4];
864 struct tms tms_before
;
865 times (& tms_before
);
866 struct timeval tv_before
;
867 gettimeofday (&tv_before
, NULL
);
868 // NB: this message is a judgement call. The other passes don't emit
869 // a "hello, I'm starting" message, but then the others aren't interactive
870 // and don't take an indefinite amount of time.
871 PROBE1(stap
, pass5__start
, &s
);
872 if (s
.verbose
) clog
<< _("Pass 5: starting run.") << endl
;
873 int rc
= remote::run(targets
);
874 struct tms tms_after
;
876 unsigned _sc_clk_tck
= sysconf (_SC_CLK_TCK
);
877 struct timeval tv_after
;
878 gettimeofday (&tv_after
, NULL
);
879 if (s
.verbose
) clog
<< "Pass 5: run completed "
884 cerr
<< _("Pass 5: run failed. Try again with another '--vp 00001' option.") << endl
;
885 //cerr << "Pass 5: run failed. "
886 // << "Try again with another '--vp 00001' option."
889 // Interrupting pass-5 to quit is normal, so we want an EXIT_SUCCESS below.
890 pending_interrupts
= 0;
892 PROBE1(stap
, pass5__end
, &s
);
898 cleanup (systemtap_session
&s
, int rc
)
900 // PASS 6: cleaning up
901 PROBE1(stap
, pass6__start
, &s
);
903 for (systemtap_session::session_map_t::iterator it
= s
.subsessions
.begin();
904 it
!= s
.subsessions
.end(); ++it
)
905 cleanup (*it
->second
, rc
);
907 // update the database information
908 if (!rc
&& s
.tapset_compile_coverage
&& !pending_interrupts
) {
909 #ifdef HAVE_LIBSQLITE3
910 update_coverage_db(s
);
912 cerr
<< _("Coverage database not available without libsqlite3") << endl
;
916 // Clean up temporary directory. Obviously, be careful with this.
919 PROBE1(stap
, pass6__end
, &s
);
923 passes_0_4_again_with_server (systemtap_session
&s
)
925 // Not a server and not already using a server.
926 assert (! s
.client_options
);
927 assert (s
.specified_servers
.empty ());
929 // Specify default server(s).
930 s
.specified_servers
.push_back ("");
932 // Remove the previous temporary directory and start fresh.
935 // Try to compile again, using the server
936 clog
<< _("Attempting compilation using a compile server")
938 int rc
= passes_0_4 (s
);
943 main (int argc
, char * const argv
[])
945 // Initialize defaults.
948 setlocale (LC_ALL
, "");
949 bindtextdomain (PACKAGE
, LOCALEDIR
);
950 textdomain (PACKAGE
);
952 // Set up our handler to catch routine signals, to allow clean
953 // and reasonably timely exit.
954 setup_signals(&handle_interrupt
);
956 // PR13520: Parse $SYSTEMTAP_DIR/rc for extra options
957 string rc_file
= s
.data_path
+ "/rc";
958 ifstream
rcf (rc_file
.c_str());
961 memset (& words
, 0, sizeof(words
));
964 while (getline (rcf
, rcline
))
966 rc
= wordexp (rcline
.c_str(), & words
, WRDE_NOCMD
|WRDE_UNDEF
|
967 (linecount
> 0 ? WRDE_APPEND
: 0));
968 // NB: WRDE_APPEND automagically reallocates words.* as more options are added.
972 int extended_argc
= words
.we_wordc
+ argc
;
973 char **extended_argv
= (char**) calloc (extended_argc
+ 1, sizeof(char*));
974 if (rc
|| !extended_argv
)
976 clog
<< _F("Error processing extra options in %s", rc_file
.c_str());
979 // Copy over the arguments *by reference*, first the ones from the rc file.
980 char **p
= & extended_argv
[0];
982 for (unsigned i
=0; i
<words
.we_wordc
; i
++) *p
++ = words
.we_wordv
[i
];
983 for (int j
=1; j
<argc
; j
++) *p
++ = argv
[j
];
986 // Process the command line.
987 rc
= s
.parse_cmdline (extended_argc
, extended_argv
);
991 if (words
.we_wordc
> 0 && s
.verbose
> 1)
992 clog
<< _F("Extra options in %s: %d\n", rc_file
.c_str(), (int)words
.we_wordc
);
994 // Check for options conflicts. Exits if errors are detected.
995 s
.check_options (extended_argc
, extended_argv
);
997 // We don't need these strings any more.
999 free (extended_argv
);
1001 // arguments parsed; get down to business
1005 // Some of the remote methods need to write temporary data, so go ahead
1006 // and create the main tempdir now.
1007 rc
= create_temp_dir (s
);
1009 // Prepare connections for each specified remote target.
1010 vector
<remote
*> targets
;
1011 bool fake_remote
=false;
1012 if (s
.remote_uris
.empty())
1015 s
.remote_uris
.push_back("direct:");
1017 for (unsigned i
= 0; rc
== 0 && i
< s
.remote_uris
.size(); ++i
)
1019 // PR13354: pass remote id#/url only in non --remote=HOST cases
1020 remote
*target
= remote::create(s
, s
.remote_uris
[i
],
1021 fake_remote
? -1 : (int)i
);
1023 targets
.push_back(target
);
1028 // Discover and loop over each unique session created by the remote targets.
1029 set
<systemtap_session
*> sessions
;
1030 for (unsigned i
= 0; i
< targets
.size(); ++i
)
1031 sessions
.insert(targets
[i
]->get_session());
1032 for (set
<systemtap_session
*>::iterator it
= sessions
.begin();
1033 rc
== 0 && !pending_interrupts
&& it
!= sessions
.end(); ++it
)
1035 systemtap_session
& ss
= **it
;
1037 clog
<< _F("Session arch: %s release: %s",
1038 ss
.architecture
.c_str(), ss
.kernel_release
.c_str()) << endl
;
1040 // If requested, query server status. This is independent of other tasks.
1041 query_server_status (ss
);
1043 // If requested, manage trust of servers. This is independent of other tasks.
1044 manage_server_trust (ss
);
1046 // Run the passes only if a script has been specified. The requirement for
1047 // a script has already been checked in systemtap_session::check_options.
1048 // Run the passes also if a dump of supported probe types has been requested via a server.
1049 if (ss
.have_script
|| (ss
.dump_probe_types
&& ! s
.specified_servers
.empty ()))
1051 // Run passes 0-4 for each unique session,
1052 // either locally or using a compile-server.
1053 ss
.init_try_server ();
1054 if ((rc
= passes_0_4 (ss
)))
1056 // Compilation failed.
1057 // Try again using a server if appropriate.
1058 if (ss
.try_server ())
1059 rc
= passes_0_4_again_with_server (ss
);
1062 else if (ss
.dump_probe_types
)
1064 // Dump a list of known probe point types, if requested.
1065 register_standard_tapsets(ss
);
1066 ss
.pattern_root
->dump (ss
);
1070 // Run pass 5, if requested
1071 if (rc
== 0 && s
.have_script
&& s
.last_pass
>= 5 && ! pending_interrupts
)
1072 rc
= pass_5 (s
, targets
);
1075 for (unsigned i
= 0; i
< targets
.size(); ++i
)
1079 return (rc
||pending_interrupts
) ? EXIT_FAILURE
: EXIT_SUCCESS
;
1082 /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */