1 // systemtap translator/driver
2 // Copyright (C) 2005-2016 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"
25 #include "client-nss.h"
28 #include "setupdwfl.h"
29 #ifdef HAVE_LIBREADLINE
30 #include "interactive.h"
39 #include "stap-probe.h"
49 #include <sys/utsname.h>
50 #include <sys/times.h>
62 uniq_list(list
<string
>& l
)
65 list
<string
>::iterator i
= l
.begin();
67 if (s
.insert(*i
).second
)
74 printscript(systemtap_session
& s
, ostream
& o
)
76 if (s
.dump_mode
== systemtap_session::dump_matched_probes
||
77 s
.dump_mode
== systemtap_session::dump_matched_probes_vars
)
79 // We go through some heroic measures to produce clean output.
80 // Record the alias and probe pointer as <name, set<derived_probe *> >
81 map
<string
,set
<derived_probe
*> > probe_list
;
83 // Pre-process the probe alias
84 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
86 assert_no_interrupts();
88 derived_probe
* p
= s
.probes
[i
];
90 p
->collect_derivation_chain (chain
);
93 p
->printsig(cerr
); cerr
<< endl
;
94 cerr
<< "chain[" << chain
.size() << "]:" << endl
;
95 for (unsigned j
=0; j
<chain
.size(); j
++)
97 cerr
<< " [" << j
<< "]: " << endl
;
98 cerr
<< "\tlocations[" << chain
[j
]->locations
.size() << "]:" << endl
;
99 for (unsigned k
=0; k
<chain
[j
]->locations
.size(); k
++)
101 cerr
<< "\t [" << k
<< "]: ";
102 chain
[j
]->locations
[k
]->print(cerr
);
105 const probe_alias
*a
= chain
[j
]->get_alias();
108 cerr
<< "\taliases[" << a
->alias_names
.size() << "]:" << endl
;
109 for (unsigned k
=0; k
<a
->alias_names
.size(); k
++)
111 cerr
<< "\t [" << k
<< "]: ";
112 a
->alias_names
[k
]->print(cerr
);
119 const string
& pp
= lex_cast(*p
->script_location());
121 // PR16730: We should only list probes that can be traced back to the
122 // user's spec, not any auxiliary probes in the tapsets.
123 // Also, do not want to the probes that are from the additional
124 // scripts (-E SCRIPT) to be listed.
125 if (!s
.is_primary_probe(p
))
128 // Now duplicate-eliminate. An alias may have expanded to
129 // several actual derived probe points, but we only want to
130 // print the alias head name once.
131 probe_list
[pp
].insert(p
);
134 // print probe name and variables if there
135 for (map
<string
, set
<derived_probe
*> >::iterator it
=probe_list
.begin(); it
!=probe_list
.end(); ++it
)
137 // probe name or alias
138 if (s
.dump_mode
== systemtap_session::dump_matched_probes_vars
&& isatty(STDOUT_FILENO
))
139 o
<< s
.colorize(it
->first
, "source");
143 // Print the locals and arguments for -L mode only
144 if (s
.dump_mode
== systemtap_session::dump_matched_probes_vars
)
146 map
<string
,unsigned> var_count
; // format <"name:type",count>
147 map
<string
,unsigned> arg_count
;
148 list
<string
> var_list
;
149 list
<string
> arg_list
;
150 // traverse set<derived_probe *> to collect all locals and arguments
151 for (set
<derived_probe
*>::iterator ix
=it
->second
.begin(); ix
!=it
->second
.end(); ++ix
)
153 derived_probe
* p
= *ix
;
154 // collect available locals of the probe
155 for (unsigned j
=0; j
<p
->locals
.size(); j
++)
158 vardecl
* v
= p
->locals
[j
];
160 var_count
[tmps
.str()]++;
161 var_list
.push_back(tmps
.str());
163 // collect arguments of the probe if there
164 list
<string
> arg_set
;
166 for (list
<string
>::iterator ia
=arg_set
.begin(); ia
!=arg_set
.end(); ++ia
) {
168 arg_list
.push_back(*ia
);
175 // print the set-intersection only
176 for (list
<string
>::iterator ir
=var_list
.begin(); ir
!=var_list
.end(); ++ir
)
177 if (var_count
.find(*ir
)->second
== it
->second
.size()) // print locals
179 for (list
<string
>::iterator ir
=arg_list
.begin(); ir
!=arg_list
.end(); ++ir
)
180 if (arg_count
.find(*ir
)->second
== it
->second
.size()) // print arguments
188 if (s
.embeds
.size() > 0)
189 o
<< _("# global embedded code") << endl
;
190 for (unsigned i
=0; i
<s
.embeds
.size(); i
++)
192 assert_no_interrupts();
193 embeddedcode
* ec
= s
.embeds
[i
];
198 if (s
.globals
.size() > 0)
199 o
<< _("# globals") << endl
;
200 for (unsigned i
=0; i
<s
.globals
.size(); i
++)
202 assert_no_interrupts();
203 vardecl
* v
= s
.globals
[i
];
205 if (s
.verbose
&& v
->init
)
213 if (s
.functions
.size() > 0)
214 o
<< _("# functions") << endl
;
215 for (map
<string
,functiondecl
*>::iterator it
= s
.functions
.begin(); it
!= s
.functions
.end(); it
++)
217 assert_no_interrupts();
218 functiondecl
* f
= it
->second
;
221 if (f
->locals
.size() > 0)
222 o
<< _(" # locals") << endl
;
223 for (unsigned j
=0; j
<f
->locals
.size(); j
++)
225 vardecl
* v
= f
->locals
[j
];
237 if (s
.probes
.size() > 0)
238 o
<< _("# probes") << endl
;
239 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
241 assert_no_interrupts();
242 derived_probe
* p
= s
.probes
[i
];
245 if (p
->locals
.size() > 0)
246 o
<< _(" # locals") << endl
;
247 for (unsigned j
=0; j
<p
->locals
.size(); j
++)
249 vardecl
* v
= p
->locals
[j
];
264 int pending_interrupts
;
267 void handle_interrupt (int)
269 // This might be nice, but we don't know our current verbosity...
270 // clog << _F("Received signal %d", sig) << endl << flush;
271 kill_stap_spawn(SIGTERM
);
273 pending_interrupts
++;
274 // Absorb the first two signals. This used to be one, but when
275 // stap is run under sudo, and then interrupted, sudo relays a
276 // redundant copy of the signal to stap, leading to an unclean shutdown.
277 if (pending_interrupts
> 2) // XXX: should be configurable? time-based?
279 char msg
[] = "Too many interrupts received, exiting.\n";
280 int rc
= write (2, msg
, sizeof(msg
)-1);
281 if (rc
) {/* Do nothing; we don't care if our last gasp went out. */ ;}
288 setup_signals (sighandler_t handler
)
292 memset(&sa
, 0, sizeof(sa
));
293 sa
.sa_handler
= handler
;
294 sigemptyset (&sa
.sa_mask
);
295 if (handler
!= SIG_IGN
)
297 sigaddset (&sa
.sa_mask
, SIGHUP
);
298 sigaddset (&sa
.sa_mask
, SIGPIPE
);
299 sigaddset (&sa
.sa_mask
, SIGINT
);
300 sigaddset (&sa
.sa_mask
, SIGTERM
);
301 sigaddset (&sa
.sa_mask
, SIGXFSZ
);
302 sigaddset (&sa
.sa_mask
, SIGXCPU
);
304 sa
.sa_flags
= SA_RESTART
;
306 sigaction (SIGHUP
, &sa
, NULL
);
307 sigaction (SIGPIPE
, &sa
, NULL
);
308 sigaction (SIGINT
, &sa
, NULL
);
309 sigaction (SIGTERM
, &sa
, NULL
);
310 sigaction (SIGXFSZ
, &sa
, NULL
);
311 sigaction (SIGXCPU
, &sa
, NULL
);
316 sdt_benchmark_thread(unsigned long i
)
318 PROBE(stap
, benchmark__thread__start
);
320 PROBE1(stap
, benchmark
, i
);
321 PROBE(stap
, benchmark__thread__end
);
326 run_sdt_benchmark(systemtap_session
& s
)
328 unsigned long loops
= s
.benchmark_sdt_loops
?: 10000000;
329 unsigned long threads
= s
.benchmark_sdt_threads
?: 1;
332 clog
<< _F("Beginning SDT benchmark with %lu loops in %lu threads.",
333 loops
, threads
) << endl
;
335 struct tms tms_before
, tms_after
;
336 struct timeval tv_before
, tv_after
;
337 unsigned _sc_clk_tck
= sysconf (_SC_CLK_TCK
);
338 times (& tms_before
);
339 gettimeofday (&tv_before
, NULL
);
341 PROBE(stap
, benchmark__start
);
343 vector
<thread
> handles
;
344 for (unsigned long i
= 0; i
< threads
; ++i
)
345 handles
.push_back(thread(sdt_benchmark_thread
, loops
));
346 for (unsigned long i
= 0; i
< threads
; ++i
)
349 PROBE(stap
, benchmark__end
);
352 gettimeofday (&tv_after
, NULL
);
354 clog
<< _F("Completed SDT benchmark in %ldusr/%ldsys/%ldreal ms.",
355 (long)(tms_after
.tms_utime
- tms_before
.tms_utime
) * 1000 / _sc_clk_tck
,
356 (long)(tms_after
.tms_stime
- tms_before
.tms_stime
) * 1000 / _sc_clk_tck
,
357 (long)((tv_after
.tv_sec
- tv_before
.tv_sec
) * 1000 +
358 ((long)tv_after
.tv_usec
- (long)tv_before
.tv_usec
) / 1000))
364 static set
<string
> files
;
365 static string path_dir
;
367 static int collect_stp(const char* fpath
, const struct stat
*,
368 int typeflag
, struct FTW
* ftwbuf
)
370 if (typeflag
== FTW_F
)
372 const char* ext
= strrchr(fpath
, '.');
373 if (ext
&& (strcmp(".stp", ext
) == 0))
376 else if (typeflag
== FTW_D
&& ftwbuf
->level
> 0)
378 // Only recurse for PATH root directory
379 if (strncmp(path_dir
.c_str(), fpath
, path_dir
.size()) != 0 ||
380 (fpath
[path_dir
.size()] != '/' && fpath
[path_dir
.size()] != '\0'))
381 return FTW_SKIP_SUBTREE
;
386 static int collect_stpm(const char* fpath
, const struct stat
*,
387 int typeflag
, struct FTW
* ftwbuf
)
389 if (typeflag
== FTW_F
)
391 const char* ext
= strrchr(fpath
, '.');
392 if (ext
&& (strcmp(".stpm", ext
) == 0))
395 else if (typeflag
== FTW_D
&& ftwbuf
->level
> 0)
397 // Only recurse for PATH root directory
398 if (strncmp(path_dir
.c_str(), fpath
, path_dir
.size()) != 0 ||
399 (fpath
[path_dir
.size()] != '/' && fpath
[path_dir
.size()] != '\0'))
400 return FTW_SKIP_SUBTREE
;
405 #ifndef HAVE_LINUX_BPF_H
407 translate_bpf_pass (systemtap_session
&)
413 // Compilation passes 0 through 4
415 passes_0_4 (systemtap_session
&s
)
419 // If we don't know the release, there's no hope either locally or on a server.
420 if (s
.kernel_release
.empty())
422 if (s
.kernel_build_tree
.empty())
423 cerr
<< _("ERROR: kernel release isn't specified") << endl
;
425 cerr
<< _F("ERROR: kernel release isn't found in \"%s\"",
426 s
.kernel_build_tree
.c_str()) << endl
;
430 // Perform passes 0 through 4 using a compile server?
431 if (! s
.specified_servers
.empty ())
433 #if NEED_BASE_CLIENT_CODE
434 compile_server_client
client (s
);
435 return client
.passes_0_4 ();
437 s
.print_warning(_("Without NSS or HTTP client support, using a compile-server is not supported by this version of systemtap"));
439 // This cannot be an attempt to use a server after a local compile failed
440 // since --use-server-on-error is locked to 'no' if we don't have
442 assert (! s
.try_server ());
443 s
.print_warning(_("Ignoring --use-server"));
447 // PASS 0: setting up
448 s
.verbose
= s
.perpass_verbose
[0];
449 PROBE1(stap
, pass0__start
, &s
);
451 // For PR1477, we used to override $PATH and $LC_ALL and other stuff
452 // here. We seem to use complete pathnames in
453 // buildrun.cxx/tapsets.cxx now, so this is not necessary. Further,
454 // it interferes with util.cxx:find_executable(), used for $PATH
457 s
.kernel_base_release
.assign(s
.kernel_release
, 0, s
.kernel_release
.find('-'));
459 // Update various paths to include the sysroot, if provided.
460 if (!s
.sysroot
.empty())
462 if (s
.update_release_sysroot
&& !s
.sysroot
.empty())
463 s
.kernel_build_tree
= s
.sysroot
+ s
.kernel_build_tree
;
464 debuginfo_path_insert_sysroot(s
.sysroot
);
467 // Now that no further changes to s.kernel_build_tree can occur, let's use it.
468 if (!s
.runtime_usermode_p())
470 if ((rc
= s
.parse_kernel_config ()) != 0
471 || (rc
= s
.parse_kernel_exports ()) != 0
472 || (rc
= s
.parse_kernel_functions ()) != 0)
474 // Try again with a server
480 // Create the name of the C source file within the temporary
481 // directory. Note the _src prefix, explained in
482 // buildrun.cxx:compile_pass()
483 s
.translated_source
= string(s
.tmpdir
) + "/" + s
.module_name
+ "_src.c";
485 PROBE1(stap
, pass0__end
, &s
);
487 struct tms tms_before
;
488 times (& tms_before
);
489 struct timeval tv_before
;
490 gettimeofday (&tv_before
, NULL
);
492 // PASS 1a: PARSING LIBRARY SCRIPTS
493 PROBE1(stap
, pass1a__start
, &s
);
495 // prep this array for tapset $n use too ... although we will reset once again for user scripts
496 s
.used_args
.resize(s
.args
.size(), false);
498 if (! s
.pass_1a_complete
)
500 // We need to handle the library scripts first because this pass
501 // gathers information on .stpm files that might be needed to
502 // parse the user script.
504 // We need to first ascertain the status of the user script, though.
505 struct stat user_file_stat
;
506 int user_file_stat_rc
= -1;
508 if (s
.script_file
== "-")
510 user_file_stat_rc
= fstat (STDIN_FILENO
, & user_file_stat
);
512 else if (s
.script_file
!= "")
514 user_file_stat_rc
= stat (s
.script_file
.c_str(), & user_file_stat
);
516 // otherwise, rc is 0 for a command line script
518 vector
<string
> version_suffixes
;
519 if (!s
.runtime_usermode_p())
521 // Construct kernel-versioning search path
522 string kvr
= s
.kernel_release
;
524 // add full kernel-version-release (2.6.NN-FOOBAR)
525 version_suffixes
.push_back ("/" + kvr
);
527 // add kernel version (2.6.NN)
528 if (kvr
!= s
.kernel_base_release
)
530 kvr
= s
.kernel_base_release
;
531 version_suffixes
.push_back ("/" + kvr
);
534 // add kernel family (2.6)
535 string::size_type dot1_index
= kvr
.find ('.');
536 string::size_type dot2_index
= kvr
.rfind ('.');
537 while (dot2_index
> dot1_index
&& dot2_index
!= string::npos
)
539 kvr
.erase(dot2_index
);
540 version_suffixes
.push_back ("/" + kvr
);
541 dot2_index
= kvr
.rfind ('.');
545 // add empty string as last element
546 version_suffixes
.push_back ("");
548 // Add arch variants of every path, just before each
549 const string
& arch
= s
.architecture
;
550 for (unsigned i
=0; i
<version_suffixes
.size(); i
+=2)
551 version_suffixes
.insert(version_suffixes
.begin() + i
,
552 version_suffixes
[i
] + "/" + arch
);
554 // Add runtime variants of every path, before everything else
555 string runtime_prefix
;
556 if (s
.runtime_mode
== systemtap_session::kernel_runtime
)
557 runtime_prefix
= "/linux";
558 else if (s
.runtime_mode
== systemtap_session::dyninst_runtime
)
559 runtime_prefix
= "/dyninst";
560 else if (s
.runtime_mode
== systemtap_session::bpf_runtime
)
561 runtime_prefix
= "/bpf";
562 if (!runtime_prefix
.empty())
563 for (unsigned i
=0; i
<version_suffixes
.size(); i
+=2)
564 version_suffixes
.insert(version_suffixes
.begin() + i
/2,
565 runtime_prefix
+ version_suffixes
[i
]);
567 // First, parse .stpm files on the include path. We need to have the
568 // resulting macro definitions available for parsing library files,
569 // but since .stpm files can consist only of '@define' constructs,
570 // we can parse each one without reference to the others.
571 set
<pair
<dev_t
, ino_t
> > seen_library_macro_files
;
572 set
<string
> seen_library_macro_files_names
;
574 for (unsigned i
=0; i
<s
.include_path
.size(); i
++)
576 // now iterate upon it
577 for (unsigned k
=0; k
<version_suffixes
.size(); k
++)
579 int flags
= FTW_ACTIONRETVAL
;
580 string dir
= s
.include_path
[i
] + version_suffixes
[k
];
582 // we need to set this for the nftw() callback
583 path_dir
= s
.include_path
[i
] + "/PATH";
584 (void) nftw(dir
.c_str(), collect_stpm
, 1, flags
);
586 unsigned prev_s_library_files
= s
.library_files
.size();
588 for (auto it
= files
.begin(); it
!= files
.end(); ++it
)
590 assert_no_interrupts();
592 struct stat tapset_file_stat
;
593 int stat_rc
= stat (it
->c_str(), & tapset_file_stat
);
594 if (stat_rc
== 0 && user_file_stat_rc
== 0 &&
595 user_file_stat
.st_dev
== tapset_file_stat
.st_dev
&&
596 user_file_stat
.st_ino
== tapset_file_stat
.st_ino
)
599 << _F("usage error: macro tapset file '%s' cannot be run directly as a session script.",
600 it
->c_str()) << endl
;
604 // PR11949: duplicate-eliminate tapset files
607 pair
<dev_t
,ino_t
> here
= make_pair(tapset_file_stat
.st_dev
,
608 tapset_file_stat
.st_ino
);
609 if (seen_library_macro_files
.find(here
) != seen_library_macro_files
.end())
612 clog
<< _F("Skipping tapset \"%s\", duplicate inode.", it
->c_str()) << endl
;
615 seen_library_macro_files
.insert (here
);
618 // PR12443: duplicate-eliminate harder
619 string full_path
= *it
;
620 string tapset_base
= s
.include_path
[i
]; // not dir; it has arch suffixes too
621 if (full_path
.size() > tapset_base
.size())
623 string tail_part
= full_path
.substr(tapset_base
.size());
624 if (seen_library_macro_files_names
.find (tail_part
) != seen_library_macro_files_names
.end())
627 clog
<< _F("Skipping tapset \"%s\", duplicate name.", it
->c_str()) << endl
;
630 seen_library_macro_files_names
.insert (tail_part
);
634 clog
<< _F("Processing tapset \"%s\"", it
->c_str()) << endl
;
636 stapfile
* f
= parse_library_macros (s
, *it
);
638 s
.print_warning(_F("macro tapset \"%s\" has errors, and will be skipped.", it
->c_str()));
640 s
.library_files
.push_back (f
);
643 unsigned next_s_library_files
= s
.library_files
.size();
644 if (s
.verbose
>1 && !files
.empty())
645 //TRANSLATORS: Searching through directories, 'processed' means 'examined so far'
646 clog
<< _F("Searched for library macro files: \"%s\", found: %zu, processed: %u",
647 dir
.c_str(), files
.size(),
648 (next_s_library_files
-prev_s_library_files
)) << endl
;
652 // Next, gather and parse the library files.
653 set
<pair
<dev_t
, ino_t
> > seen_library_files
;
654 set
<string
> seen_library_files_names
;
656 for (unsigned i
=0; i
<s
.include_path
.size(); i
++)
658 // now iterate upon it
659 for (unsigned k
=0; k
<version_suffixes
.size(); k
++)
661 int flags
= FTW_ACTIONRETVAL
;
662 string dir
= s
.include_path
[i
] + version_suffixes
[k
];
664 // we need to set this for the nftw() callback
665 path_dir
= s
.include_path
[i
] + "/PATH";
666 (void) nftw(dir
.c_str(), collect_stp
, 1, flags
);
668 unsigned prev_s_library_files
= s
.library_files
.size();
670 for (auto it
= files
.begin(); it
!= files
.end(); ++it
)
672 unsigned tapset_flags
= pf_guru
| pf_squash_errors
;
674 // The first path is special, as it's the builtin tapset.
675 // Allow all features no matter what s.compatible says.
677 tapset_flags
|= pf_no_compatible
;
679 if (it
->find("/PATH/") != string::npos
)
680 tapset_flags
|= pf_auto_path
;
682 assert_no_interrupts();
684 struct stat tapset_file_stat
;
685 int stat_rc
= stat (it
->c_str(), & tapset_file_stat
);
686 if (stat_rc
== 0 && user_file_stat_rc
== 0 &&
687 user_file_stat
.st_dev
== tapset_file_stat
.st_dev
&&
688 user_file_stat
.st_ino
== tapset_file_stat
.st_ino
)
691 << _F("usage error: tapset file '%s' cannot be run directly as a session script.",
692 it
->c_str()) << endl
;
696 // PR11949: duplicate-eliminate tapset files
699 pair
<dev_t
,ino_t
> here
= make_pair(tapset_file_stat
.st_dev
,
700 tapset_file_stat
.st_ino
);
701 if (seen_library_files
.find(here
) != seen_library_files
.end())
704 clog
<< _F("Skipping tapset \"%s\", duplicate inode.", it
->c_str()) << endl
;
707 seen_library_files
.insert (here
);
710 // PR12443: duplicate-eliminate harder
711 string full_path
= *it
;
712 string tapset_base
= s
.include_path
[i
]; // not dir; it has arch suffixes too
713 if (full_path
.size() > tapset_base
.size())
715 string tail_part
= full_path
.substr(tapset_base
.size());
716 if (seen_library_files_names
.find (tail_part
) != seen_library_files_names
.end())
719 clog
<< _F("Skipping tapset \"%s\", duplicate name.", it
->c_str()) << endl
;
722 seen_library_files_names
.insert (tail_part
);
726 clog
<< _F("Processing tapset \"%s\"", it
->c_str()) << endl
;
728 // NB: we don't need to restrict privilege only for
729 // /usr/share/systemtap, i.e., excluding
730 // user-specified $XDG_DATA_DIRS. That's because
731 // stapdev gets root-equivalent privileges anyway;
732 // stapsys and stapusr use a remote compilation with
733 // a trusted environment, where client-side
734 // $XDG_DATA_DIRS are not passed.
736 stapfile
* f
= parse (s
, *it
, tapset_flags
);
738 s
.print_warning(_F("tapset \"%s\" has errors, and will be skipped", it
->c_str()));
740 s
.library_files
.push_back (f
);
743 unsigned next_s_library_files
= s
.library_files
.size();
744 if (s
.verbose
>1 && !files
.empty())
745 //TRANSLATORS: Searching through directories, 'processed' means 'examined so far'
746 clog
<< _F("Searched: \"%s\", found: %zu, processed: %u",
747 dir
.c_str(), files
.size(),
748 (next_s_library_files
-prev_s_library_files
)) << endl
;
755 // Now that we've made it through pass 1a, remember this so we
756 // don't have to do this again in interactive mode. This doesn't
757 // effect non-interactive mode.
758 s
.pass_1a_complete
= true;
761 // PASS 1b: PARSING USER SCRIPT
762 PROBE1(stap
, pass1b__start
, &s
);
764 // reset for user scripts -- it's their use of $* we care about
765 // except that tapsets like argv.stp can consume $parms
766 fill(s
.used_args
.begin(), s
.used_args
.end(), false);
768 // Only try to parse a user script if the user provided one, or if we have to
769 // make one (as is the case for listing mode). Otherwise, s.user_script
771 if (!s
.script_file
.empty() ||
772 !s
.cmdline_script
.empty() ||
773 s
.dump_mode
== systemtap_session::dump_matched_probes
||
774 s
.dump_mode
== systemtap_session::dump_matched_probes_vars
)
776 unsigned user_flags
= s
.guru_mode
? pf_guru
: 0;
777 user_flags
|= pf_user_file
;
778 if (s
.script_file
== "-")
780 if (s
.stdin_script
.str().empty())
781 s
.stdin_script
<< cin
.rdbuf();
782 s
.user_files
.push_back (parse (s
, "<input>", s
.stdin_script
,
785 else if (s
.script_file
!= "")
787 s
.user_files
.push_back (parse (s
, s
.script_file
, user_flags
));
789 else if (s
.cmdline_script
!= "")
791 istringstream
ii (s
.cmdline_script
);
792 s
.user_files
.push_back(parse (s
, "<input>", ii
, user_flags
));
796 istringstream
ii ("probe " + s
.dump_matched_pattern
+ " {}");
797 s
.user_files
.push_back (parse (s
, "<input>", ii
, user_flags
));
800 // parses the additional script(s) (-E script). does so even if in listing
801 // mode, incase there is something special in the additional script(s),
802 // like a macro or alias. give them a unique name to differentiate the
803 // scripts that were inputted.
805 for (vector
<string
>::iterator script
= s
.additional_scripts
.begin(); script
!= s
.additional_scripts
.end(); script
++)
807 string input_name
= "<input" + lex_cast(count
) + ">";
808 istringstream
ii (*script
);
809 s
.user_files
.push_back(parse (s
, input_name
, ii
, user_flags
));
813 for(vector
<stapfile
*>::iterator it
= s
.user_files
.begin(); it
!= s
.user_files
.end(); it
++)
817 // Syntax errors already printed.
822 else if (s
.cmdline_script
.empty() &&
823 s
.dump_mode
== systemtap_session::dump_none
) // -e ''
825 cerr
<< _("Input file '<input>' is empty.") << endl
;
829 // Dump a list of probe aliases picked up, if requested
830 if (s
.dump_mode
== systemtap_session::dump_probe_aliases
)
833 vector
<stapfile
*>::const_iterator file
;
834 for (file
= s
.library_files
.begin();
835 file
!= s
.library_files
.end(); ++file
)
837 vector
<probe_alias
*>::const_iterator alias
;
838 for (alias
= (*file
)->aliases
.begin();
839 alias
!= (*file
)->aliases
.end(); ++alias
)
842 (*alias
)->printsig(ss
);
843 string str
= ss
.str();
844 if (!s
.verbose
&& startswith(str
, "_"))
850 set
<string
>::iterator alias
;
851 for (alias
= aliases
.begin();
852 alias
!= aliases
.end(); ++alias
)
854 cout
<< *alias
<< endl
;
857 // Dump the parse tree if this is the last pass
858 else if (rc
== 0 && s
.last_pass
== 1)
860 cout
<< _("# parse tree dump") << endl
;
861 for (vector
<stapfile
*>::iterator it
= s
.user_files
.begin(); it
!= s
.user_files
.end(); it
++)
865 for (unsigned i
=0; i
<s
.library_files
.size(); i
++)
867 s
.library_files
[i
]->print (cout
);
872 struct tms tms_after
;
874 unsigned _sc_clk_tck
= sysconf (_SC_CLK_TCK
);
875 struct timeval tv_after
;
876 gettimeofday (&tv_after
, NULL
);
878 #define TIMESPRINT _("in ") << \
879 (tms_after.tms_cutime + tms_after.tms_utime \
880 - tms_before.tms_cutime - tms_before.tms_utime) * 1000 / (_sc_clk_tck) << "usr/" \
881 << (tms_after.tms_cstime + tms_after.tms_stime \
882 - tms_before.tms_cstime - tms_before.tms_stime) * 1000 / (_sc_clk_tck) << "sys/" \
883 << ((tv_after.tv_sec - tv_before.tv_sec) * 1000 + \
884 ((long)tv_after.tv_usec - (long)tv_before.tv_usec) / 1000) << "real ms."
886 // syntax errors, if any, are already printed
889 // XXX also include a count of helper macro files loaded (.stpm)?
890 int n
= int(s
.library_files
.size());
891 clog
<< _("Pass 1: parsed user script and ")
892 << _NF("%d library script ", "%d library scripts ", n
, n
)
898 if (rc
&& !s
.dump_mode
)
899 cerr
<< _("Pass 1: parse failed. [man error::pass1]") << endl
;
901 PROBE1(stap
, pass1__end
, &s
);
903 assert_no_interrupts();
904 if (rc
|| s
.last_pass
== 1 ||
905 s
.dump_mode
== systemtap_session::dump_probe_aliases
)
908 times (& tms_before
);
909 gettimeofday (&tv_before
, NULL
);
911 // PASS 2: ELABORATION
912 s
.verbose
= s
.perpass_verbose
[1];
913 PROBE1(stap
, pass2__start
, &s
);
914 rc
= semantic_pass (s
);
916 // http handled probes need probe information from pass 2
917 if (! s
.http_servers
.empty ())
919 #if NEED_BASE_CLIENT_CODE
920 compile_server_client
client (s
);
921 return client
.passes_0_4 ();
923 s
.print_warning(_("Without NSS or HTTP client support, using a compile-server is not supported by this version of systemtap"));
925 // This cannot be an attempt to use a server after a local compile failed
926 // since --use-server-on-error is locked to 'no' if we don't have
928 assert (! s
.try_server ());
929 s
.print_warning(_("Ignoring --use-server"));
933 // Dump a list of known probe point types, if requested.
934 if (s
.dump_mode
== systemtap_session::dump_probe_types
)
935 s
.pattern_root
->dump (s
);
936 // Dump a list of functions we picked up, if requested.
937 else if (s
.dump_mode
== systemtap_session::dump_functions
)
939 map
<string
,functiondecl
*>::const_iterator func
;
940 for (func
= s
.functions
.begin();
941 func
!= s
.functions
.end(); ++func
)
943 functiondecl
& curfunc
= *func
->second
;
944 if (curfunc
.synthetic
)
946 if (!startswith(curfunc
.name
, "__global_"))
948 if (!s
.verbose
&& startswith(curfunc
.name
, "__global__"))
950 curfunc
.printsigtags(cout
, s
.verbose
>0 /* all_tags */ );
954 // Dump the whole script if requested, or if we stop at 2
955 else if (s
.dump_mode
== systemtap_session::dump_matched_probes
||
956 s
.dump_mode
== systemtap_session::dump_matched_probes_vars
||
957 (rc
== 0 && s
.last_pass
== 2) ||
958 (rc
!= 0 && s
.verbose
> 2))
959 printscript(s
, cout
);
962 gettimeofday (&tv_after
, NULL
);
965 int np
= s
.probes
.size();
966 int nf
= s
.functions
.size();
967 int ne
= s
.embeds
.size();
968 int ng
= s
.globals
.size();
969 clog
<< _("Pass 2: analyzed script: ")
970 << _NF("%d probe, ", "%d probes, ", np
, np
)
971 << _NF("%d function, ", "%d functions, ", nf
, nf
)
972 << _NF("%d embed, ", "%d embeds, ", ne
, ne
)
973 << _NF("%d global ", "%d globals ", ng
, ng
)
979 missing_rpm_list_print(s
, "-debuginfo");
981 // Check for unused command line parameters. But - if the argv
982 // tapset was selected for inclusion, then the user-script need not
983 // use $* directly, so we want to suppress the warning in this case.
984 // This is hacky, but we don't have a formal way of tracking tokens
985 // that came from command line arguments so as to do set-subtraction
988 bool argc_found
=false, argv_found
=false;
989 for (unsigned i
= 0; i
<s
.globals
.size(); i
++) {
990 if (s
.globals
[i
]->unmangled_name
== "argc") argc_found
= true;
991 if (s
.globals
[i
]->unmangled_name
== "argv") argv_found
= true;
993 if (!argc_found
&& !argv_found
)
994 for (unsigned i
= 0; i
<s
.used_args
.size(); i
++)
995 if (! s
.used_args
[i
])
996 s
.print_warning (_F("unused command line option $%u/@%u", i
+1, i
+1));
998 if (rc
&& !s
.dump_mode
&& !s
.try_server ())
999 cerr
<< _("Pass 2: analysis failed. [man error::pass2]") << endl
;
1001 PROBE1(stap
, pass2__end
, &s
);
1003 assert_no_interrupts();
1004 // NB: none of the dump modes need to go beyond pass-2. If this changes, break
1005 // into individual modes here.
1006 if (rc
|| s
.last_pass
== 2 || s
.dump_mode
)
1009 rc
= prepare_translate_pass (s
);
1010 assert_no_interrupts();
1013 // Generate hash. There isn't any point in generating the hash
1014 // if last_pass is 2, since we'll quit before using it.
1015 if (s
.use_script_cache
)
1018 unsigned saved_verbose
;
1021 // Make sure we're in verbose mode, so that printscript()
1022 // will output function/probe bodies.
1023 saved_verbose
= s
.verbose
;
1025 printscript(s
, o
); // Print script to 'o'
1026 s
.verbose
= saved_verbose
;
1030 find_script_hash (s
, o
.str());
1032 // See if we can use cached source/module.
1033 if (get_script_from_cache(s
))
1035 // We may still need to build uprobes, if it's not also cached.
1037 rc
= uprobes_pass(s
);
1039 // If our last pass isn't 5, we're done (since passes 3 and
1040 // 4 just generate what we just pulled out of the cache).
1041 assert_no_interrupts();
1042 if (rc
|| s
.last_pass
< 5) return rc
;
1044 // Short-circuit to pass 5.
1049 // PASS 3: TRANSLATION
1050 // (BPF does translation and compilation at once in pass 4.)
1051 if (s
.runtime_mode
!= systemtap_session::bpf_runtime
)
1053 s
.verbose
= s
.perpass_verbose
[2];
1054 times (& tms_before
);
1055 gettimeofday (&tv_before
, NULL
);
1056 PROBE1(stap
, pass3__start
, &s
);
1058 rc
= translate_pass (s
);
1060 if (! rc
&& s
.last_pass
== 3)
1062 ifstream
i (s
.translated_source
.c_str());
1066 times (& tms_after
);
1067 gettimeofday (&tv_after
, NULL
);
1070 clog
<< _("Pass 3: translated to C into \"")
1071 << s
.translated_source
1077 if (rc
&& ! s
.try_server ())
1078 cerr
<< _("Pass 3: translation failed. [man error::pass3]") << endl
;
1080 PROBE1(stap
, pass3__end
, &s
);
1082 assert_no_interrupts();
1083 if (rc
|| s
.last_pass
== 3)
1087 // PASS 4: COMPILATION
1088 s
.verbose
= s
.perpass_verbose
[3];
1089 times (& tms_before
);
1090 gettimeofday (&tv_before
, NULL
);
1091 PROBE1(stap
, pass4__start
, &s
);
1093 if (s
.runtime_mode
== systemtap_session::bpf_runtime
)
1094 rc
= translate_bpf_pass (s
);
1099 find_stapconf_hash(s
);
1100 get_stapconf_from_cache(s
);
1102 rc
= compile_pass (s
);
1105 if (! rc
&& s
.last_pass
<= 4)
1107 cout
<< ((s
.hash_path
== "") ? s
.module_filename() : s
.hash_path
);
1111 times (& tms_after
);
1112 gettimeofday (&tv_after
, NULL
);
1116 if (s
.runtime_mode
== systemtap_session::bpf_runtime
)
1117 clog
<< _("Pass 4: compiled BPF into \"");
1119 clog
<< _("Pass 4: compiled C into \"");
1120 clog
<< s
.module_filename() << "\" " << TIMESPRINT
<< endl
;
1123 if (rc
&& ! s
.try_server ())
1124 cerr
<< _("Pass 4: compilation failed. [man error::pass4]") << endl
;
1127 // Update cache. Cache cleaning is kicked off at the
1128 // beginning of this function.
1129 if (s
.use_script_cache
)
1130 add_script_to_cache(s
);
1131 if (s
.use_cache
&& !s
.runtime_usermode_p())
1132 add_stapconf_to_cache(s
);
1134 // We may need to save the module in $CWD if the cache was
1135 // inaccessible for some reason.
1136 if (! s
.use_script_cache
&& s
.last_pass
<= 4)
1137 s
.save_module
= true;
1139 // Copy module to the current directory.
1140 if (s
.save_module
&& !pending_interrupts
)
1142 string module_src_path
= s
.tmpdir
+ "/" + s
.module_filename();
1143 string module_dest_path
= s
.module_filename();
1144 copy_file(module_src_path
, module_dest_path
, s
.verbose
> 1);
1147 // Copy uprobes module to the current directory.
1148 if (s
.save_uprobes
&& !s
.uprobes_path
.empty() && !pending_interrupts
)
1150 rc
= create_dir("uprobes");
1152 copy_file(s
.uprobes_path
, "uprobes/uprobes.ko", s
.verbose
> 1);
1156 PROBE1(stap
, pass4__end
, &s
);
1162 pass_5 (systemtap_session
&s
, vector
<remote
*> targets
)
1165 s
.verbose
= s
.perpass_verbose
[4];
1166 struct tms tms_before
;
1167 times (& tms_before
);
1168 struct timeval tv_before
;
1169 gettimeofday (&tv_before
, NULL
);
1170 // NB: this message is a judgement call. The other passes don't emit
1171 // a "hello, I'm starting" message, but then the others aren't interactive
1172 // and don't take an indefinite amount of time.
1173 PROBE1(stap
, pass5__start
, &s
);
1174 if (s
.verbose
) clog
<< _("Pass 5: starting run.") << endl
;
1175 int rc
= remote::run(targets
);
1176 struct tms tms_after
;
1177 times (& tms_after
);
1178 unsigned _sc_clk_tck
= sysconf (_SC_CLK_TCK
);
1179 struct timeval tv_after
;
1180 gettimeofday (&tv_after
, NULL
);
1181 if (s
.verbose
) clog
<< _("Pass 5: run completed ")
1186 cerr
<< _("Pass 5: run failed. [man error::pass5]") << endl
;
1188 // Interrupting pass-5 to quit is normal, so we want an EXIT_SUCCESS below.
1189 pending_interrupts
= 0;
1191 PROBE1(stap
, pass5__end
, &s
);
1197 cleanup (systemtap_session
&s
, int rc
)
1199 // PASS 6: cleaning up
1200 PROBE1(stap
, pass6__start
, &s
);
1202 for (systemtap_session::session_map_t::iterator it
= s
.subsessions
.begin();
1203 it
!= s
.subsessions
.end(); ++it
)
1204 cleanup (*it
->second
, rc
);
1206 // update the database information
1207 if (!rc
&& s
.tapset_compile_coverage
&& !pending_interrupts
) {
1208 #ifdef HAVE_LIBSQLITE3
1209 update_coverage_db(s
);
1211 cerr
<< _("Coverage database not available without libsqlite3") << endl
;
1215 s
.report_suppression();
1217 PROBE1(stap
, pass6__end
, &s
);
1221 passes_0_4_again_with_server (systemtap_session
&s
)
1223 // Not a server and not already using a server.
1224 assert (! s
.client_options
);
1225 assert (s
.specified_servers
.empty ());
1227 // Specify default server(s).
1228 s
.specified_servers
.push_back ("");
1230 // Reset the previous temporary directory and start fresh
1233 // Try to compile again, using the server
1234 clog
<< _("Attempting compilation using a compile server")
1237 int rc
= passes_0_4 (s
);
1242 main (int argc
, char * const argv
[])
1244 // Initialize defaults.
1246 systemtap_session s
;
1248 setlocale (LC_ALL
, "");
1249 bindtextdomain (PACKAGE
, LOCALEDIR
);
1250 textdomain (PACKAGE
);
1253 // Set up our handler to catch routine signals, to allow clean
1254 // and reasonably timely exit.
1255 setup_signals(&handle_interrupt
);
1257 // PR13520: Parse $SYSTEMTAP_DIR/rc for extra options
1258 string rc_file
= s
.data_path
+ "/rc";
1259 ifstream
rcf (rc_file
.c_str());
1262 memset (& words
, 0, sizeof(words
));
1265 while (getline (rcf
, rcline
))
1267 rc
= wordexp (rcline
.c_str(), & words
, WRDE_NOCMD
|WRDE_UNDEF
|
1268 (linecount
> 0 ? WRDE_APPEND
: 0));
1269 // NB: WRDE_APPEND automagically reallocates words.* as more options are added.
1275 int extended_argc
= words
.we_wordc
+ argc
;
1276 char **extended_argv
= (char**) calloc (extended_argc
+ 1, sizeof(char*));
1277 if (rc
|| !extended_argv
)
1279 clog
<< _F("Error processing extra options in %s", rc_file
.c_str());
1280 return EXIT_FAILURE
;
1282 // Copy over the arguments *by reference*, first the ones from the rc file.
1283 char **p
= & extended_argv
[0];
1285 for (unsigned i
=0; i
<words
.we_wordc
; i
++) *p
++ = words
.we_wordv
[i
];
1286 for (int j
=1; j
<argc
; j
++) *p
++ = argv
[j
];
1289 // Process the command line.
1290 rc
= s
.parse_cmdline (extended_argc
, extended_argv
);
1294 // Create the temp dir.
1297 if (words
.we_wordc
> 0 && s
.verbose
> 1)
1298 clog
<< _F("Extra options in %s: %d\n", rc_file
.c_str(), (int)words
.we_wordc
);
1300 // Check for options conflicts. Exits if errors are detected.
1301 s
.check_options (extended_argc
, extended_argv
);
1303 // We don't need these strings any more.
1305 free (extended_argv
);
1307 // arguments parsed; get down to business
1311 // Need to send the verbose message here, rather than in the session ctor, since
1312 // we didn't know if verbose was set.
1313 if (rc
== 0 && s
.verbose
>1)
1314 clog
<< _F("Created temporary directory \"%s\"", s
.tmpdir
.c_str()) << endl
;
1316 // Run the benchmark and quit right away.
1317 if (s
.benchmark_sdt_loops
|| s
.benchmark_sdt_threads
)
1318 return run_sdt_benchmark(s
);
1320 // Prepare connections for each specified remote target.
1321 vector
<remote
*> targets
;
1322 bool fake_remote
=false;
1323 if (s
.remote_uris
.empty())
1326 s
.remote_uris
.push_back("direct:");
1328 for (unsigned i
= 0; rc
== 0 && i
< s
.remote_uris
.size(); ++i
)
1330 // PR13354: pass remote id#/url only in non --remote=HOST cases
1331 remote
*target
= remote::create(s
, s
.remote_uris
[i
],
1332 fake_remote
? -1 : (int)i
);
1334 targets
.push_back(target
);
1339 // Discover and loop over each unique session created by the remote targets.
1340 set
<systemtap_session
*> sessions
;
1341 for (unsigned i
= 0; i
< targets
.size(); ++i
)
1342 sessions
.insert(targets
[i
]->get_session());
1344 // FIXME: For now, only attempt local interactive use.
1345 if (s
.interactive_mode
&& fake_remote
)
1347 #ifdef HAVE_LIBREADLINE
1348 rc
= interactive_mode (s
, targets
);
1353 for (set
<systemtap_session
*>::iterator it
= sessions
.begin();
1354 rc
== 0 && !pending_interrupts
&& it
!= sessions
.end(); ++it
)
1356 systemtap_session
& ss
= **it
;
1358 clog
<< _F("Session arch: %s release: %s",
1359 ss
.architecture
.c_str(), ss
.kernel_release
.c_str())
1363 // If requested, query server status. This is independent
1365 nss_client_query_server_status (ss
);
1367 // If requested, manage trust of servers. This is
1368 // independent of other tasks.
1369 nss_client_manage_server_trust (ss
);
1372 // Run the passes only if a script has been specified or
1373 // if we're dumping something. The requirement for a
1374 // script has already been checked in
1375 // systemtap_session::check_options.
1376 if (ss
.have_script
|| ss
.dump_mode
)
1378 // Run passes 0-4 for each unique session, either
1379 // locally or using a compile-server.
1380 ss
.init_try_server ();
1381 if ((rc
= passes_0_4 (ss
)))
1383 // Compilation failed.
1384 // Try again using a server if appropriate.
1385 if (ss
.try_server ())
1386 rc
= passes_0_4_again_with_server (ss
);
1388 if (rc
|| s
.perpass_verbose
[0] >= 1)
1389 s
.explain_auto_options ();
1393 // Run pass 5, if requested
1394 if (rc
== 0 && s
.have_script
&& s
.last_pass
>= 5 && ! pending_interrupts
)
1395 rc
= pass_5 (s
, targets
);
1399 for (unsigned i
= 0; i
< targets
.size(); ++i
)
1403 assert_no_interrupts();
1404 return (rc
) ? EXIT_FAILURE
: EXIT_SUCCESS
;
1406 catch (const interrupt_exception
& e
) {
1407 // User entered ctrl-c, exit quietly.
1408 return EXIT_FAILURE
;
1410 catch (const exit_exception
& e
) {
1411 // Exiting for any quiet reason.
1414 catch (const exception
&e
) {
1415 // Some other uncaught exception.
1416 cerr
<< e
.what() << endl
;
1417 return EXIT_FAILURE
;
1420 // Catch all other unknown exceptions.
1421 cerr
<< _("ERROR: caught unknown exception!") << endl
;
1422 return EXIT_FAILURE
;
1426 /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */