1 // systemtap translator/driver
2 // Copyright (C) 2005-2014 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"
27 #include "setupdwfl.h"
34 #include "stap-probe.h"
42 #include <sys/utsname.h>
43 #include <sys/times.h>
54 uniq_list(list
<string
>& l
)
57 list
<string
>::iterator i
= l
.begin();
59 if (s
.insert(*i
).second
)
66 printscript(systemtap_session
& s
, ostream
& o
)
68 if (s
.dump_mode
== systemtap_session::dump_matched_probes
||
69 s
.dump_mode
== systemtap_session::dump_matched_probes_vars
)
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
;
75 // Pre-process the probe alias
76 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
78 assert_no_interrupts();
80 derived_probe
* p
= s
.probes
[i
];
82 p
->collect_derivation_chain (chain
);
85 p
->printsig(cerr
); cerr
<< endl
;
86 cerr
<< "chain[" << chain
.size() << "]:" << endl
;
87 for (unsigned j
=0; j
<chain
.size(); j
++)
89 cerr
<< " [" << j
<< "]: " << endl
;
90 cerr
<< "\tlocations[" << chain
[j
]->locations
.size() << "]:" << endl
;
91 for (unsigned k
=0; k
<chain
[j
]->locations
.size(); k
++)
93 cerr
<< "\t [" << k
<< "]: ";
94 chain
[j
]->locations
[k
]->print(cerr
);
97 const probe_alias
*a
= chain
[j
]->get_alias();
100 cerr
<< "\taliases[" << a
->alias_names
.size() << "]:" << endl
;
101 for (unsigned k
=0; k
<a
->alias_names
.size(); k
++)
103 cerr
<< "\t [" << k
<< "]: ";
104 a
->alias_names
[k
]->print(cerr
);
111 const string
& pp
= lex_cast(*p
->script_location());
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.
115 // Also, do not want to the probes that are from the additional
116 // scripts (-E SCRIPT) to be listed.
117 if (!s
.is_primary_probe(p
))
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
);
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
)
129 o
<< it
->first
; // probe name or alias
131 // Print the locals and arguments for -L mode only
132 if (s
.dump_mode
== systemtap_session::dump_matched_probes_vars
)
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
)
141 derived_probe
* p
= *ix
;
142 // collect available locals of the probe
143 for (unsigned j
=0; j
<p
->locals
.size(); j
++)
146 vardecl
* v
= p
->locals
[j
];
148 var_count
[tmps
.str()]++;
149 var_list
.push_back(tmps
.str());
151 // collect arguments of the probe if there
152 list
<string
> arg_set
;
154 for (list
<string
>::iterator ia
=arg_set
.begin(); ia
!=arg_set
.end(); ++ia
) {
156 arg_list
.push_back(*ia
);
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
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
176 if (s
.embeds
.size() > 0)
177 o
<< _("# global embedded code") << endl
;
178 for (unsigned i
=0; i
<s
.embeds
.size(); i
++)
180 assert_no_interrupts();
181 embeddedcode
* ec
= s
.embeds
[i
];
186 if (s
.globals
.size() > 0)
187 o
<< _("# globals") << endl
;
188 for (unsigned i
=0; i
<s
.globals
.size(); i
++)
190 assert_no_interrupts();
191 vardecl
* v
= s
.globals
[i
];
193 if (s
.verbose
&& v
->init
)
201 if (s
.functions
.size() > 0)
202 o
<< _("# functions") << endl
;
203 for (map
<string
,functiondecl
*>::iterator it
= s
.functions
.begin(); it
!= s
.functions
.end(); it
++)
205 assert_no_interrupts();
206 functiondecl
* f
= it
->second
;
209 if (f
->locals
.size() > 0)
210 o
<< _(" # locals") << endl
;
211 for (unsigned j
=0; j
<f
->locals
.size(); j
++)
213 vardecl
* v
= f
->locals
[j
];
225 if (s
.probes
.size() > 0)
226 o
<< _("# probes") << endl
;
227 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
229 assert_no_interrupts();
230 derived_probe
* p
= s
.probes
[i
];
233 if (p
->locals
.size() > 0)
234 o
<< _(" # locals") << endl
;
235 for (unsigned j
=0; j
<p
->locals
.size(); j
++)
237 vardecl
* v
= p
->locals
[j
];
252 int pending_interrupts
;
255 void handle_interrupt (int)
257 // This might be nice, but we don't know our current verbosity...
258 // clog << _F("Received signal %d", sig) << endl << flush;
259 kill_stap_spawn(SIGTERM
);
261 pending_interrupts
++;
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?
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. */ ;}
276 setup_signals (sighandler_t handler
)
280 memset(&sa
, 0, sizeof(sa
));
281 sa
.sa_handler
= handler
;
282 sigemptyset (&sa
.sa_mask
);
283 if (handler
!= SIG_IGN
)
285 sigaddset (&sa
.sa_mask
, SIGHUP
);
286 sigaddset (&sa
.sa_mask
, SIGPIPE
);
287 sigaddset (&sa
.sa_mask
, SIGINT
);
288 sigaddset (&sa
.sa_mask
, SIGTERM
);
289 sigaddset (&sa
.sa_mask
, SIGXFSZ
);
290 sigaddset (&sa
.sa_mask
, SIGXCPU
);
292 sa
.sa_flags
= SA_RESTART
;
294 sigaction (SIGHUP
, &sa
, NULL
);
295 sigaction (SIGPIPE
, &sa
, NULL
);
296 sigaction (SIGINT
, &sa
, NULL
);
297 sigaction (SIGTERM
, &sa
, NULL
);
298 sigaction (SIGXFSZ
, &sa
, NULL
);
299 sigaction (SIGXCPU
, &sa
, NULL
);
304 sdt_benchmark_thread(void* p
)
306 unsigned long i
= *(unsigned long*)p
;
307 PROBE(stap
, benchmark__thread__start
);
309 PROBE1(stap
, benchmark
, i
);
310 PROBE(stap
, benchmark__thread__end
);
316 run_sdt_benchmark(systemtap_session
& s
)
318 unsigned long loops
= s
.benchmark_sdt_loops
?: 10000000;
319 unsigned long threads
= s
.benchmark_sdt_threads
?: 1;
322 clog
<< _F("Beginning SDT benchmark with %lu loops in %lu threads.",
323 loops
, threads
) << endl
;
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
);
331 PROBE(stap
, benchmark__start
);
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
);
339 PROBE(stap
, benchmark__end
);
342 gettimeofday (&tv_after
, NULL
);
344 clog
<< _F("Completed SDT benchmark in %ldusr/%ldsys/%ldreal ms.",
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 +
348 ((long)tv_after
.tv_usec
- (long)tv_before
.tv_usec
) / 1000))
355 // Compilation passes 0 through 4
357 passes_0_4 (systemtap_session
&s
)
361 // If we don't know the release, there's no hope either locally or on a server.
362 if (s
.kernel_release
.empty())
364 if (s
.kernel_build_tree
.empty())
365 cerr
<< _("ERROR: kernel release isn't specified") << endl
;
367 cerr
<< _F("ERROR: kernel release isn't found in \"%s\"",
368 s
.kernel_build_tree
.c_str()) << endl
;
372 // Perform passes 0 through 4 using a compile server?
373 if (! s
.specified_servers
.empty ())
376 compile_server_client
client (s
);
377 return client
.passes_0_4 ();
379 s
.print_warning(_("Without NSS, using a compile-server is not supported by this version of systemtap"));
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
384 assert (! s
.try_server ());
385 s
.print_warning(_("Ignoring --use-server"));
389 // PASS 0: setting up
390 s
.verbose
= s
.perpass_verbose
[0];
391 PROBE1(stap
, pass0__start
, &s
);
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
399 s
.kernel_base_release
.assign(s
.kernel_release
, 0, s
.kernel_release
.find('-'));
401 // Update various paths to include the sysroot, if provided.
402 if (!s
.sysroot
.empty())
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
);
409 // Now that no further changes to s.kernel_build_tree can occur, let's use it.
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)
415 // Try again with a server
421 // Create the name of the C source file within the temporary
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";
426 PROBE1(stap
, pass0__end
, &s
);
428 struct tms tms_before
;
429 times (& tms_before
);
430 struct timeval tv_before
;
431 gettimeofday (&tv_before
, NULL
);
433 // PASS 1a: PARSING LIBRARY SCRIPTS
434 PROBE1(stap
, pass1a__start
, &s
);
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.
440 // We need to first ascertain the status of the user script, though.
441 struct stat user_file_stat
;
442 int user_file_stat_rc
= -1;
444 if (s
.script_file
== "-")
446 user_file_stat_rc
= fstat (STDIN_FILENO
, & user_file_stat
);
448 else if (s
.script_file
!= "")
450 user_file_stat_rc
= stat (s
.script_file
.c_str(), & user_file_stat
);
452 // otherwise, rc is 0 for a command line script
454 vector
<string
> version_suffixes
;
455 if (s
.runtime_mode
== systemtap_session::kernel_runtime
)
457 // Construct kernel-versioning search path
458 string kvr
= s
.kernel_release
;
460 // add full kernel-version-release (2.6.NN-FOOBAR)
461 version_suffixes
.push_back ("/" + kvr
);
463 // add kernel version (2.6.NN)
464 if (kvr
!= s
.kernel_base_release
)
466 kvr
= s
.kernel_base_release
;
467 version_suffixes
.push_back ("/" + kvr
);
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
)
475 kvr
.erase(dot2_index
);
476 version_suffixes
.push_back ("/" + kvr
);
477 dot2_index
= kvr
.rfind ('.');
481 // add empty string as last element
482 version_suffixes
.push_back ("");
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
);
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
]);
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
;
506 set
<string
> seen_library_macro_files_names
;
508 for (unsigned i
=0; i
<s
.include_path
.size(); i
++)
510 // now iterate upon it
511 for (unsigned k
=0; k
<version_suffixes
.size(); k
++)
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
)
518 // GLOB_NOMATCH is acceptable
520 unsigned prev_s_library_files
= s
.library_files
.size();
522 for (unsigned j
=0; j
<globbuf
.gl_pathc
; j
++)
524 assert_no_interrupts();
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
)
533 << _F("usage error: macro tapset file '%s' cannot be run directly as a session script.",
534 globbuf
.gl_pathv
[j
]) << endl
;
538 // PR11949: duplicate-eliminate tapset files
541 pair
<dev_t
,ino_t
> here
= make_pair(tapset_file_stat
.st_dev
,
542 tapset_file_stat
.st_ino
);
543 if (seen_library_macro_files
.find(here
) != seen_library_macro_files
.end()) {
545 clog
<< _F("Skipping tapset \"%s\", duplicate inode.", globbuf
.gl_pathv
[j
]) << endl
;
548 seen_library_macro_files
.insert (here
);
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()) {
558 clog
<< _F("Skipping tapset \"%s\", duplicate name.", globbuf
.gl_pathv
[j
]) << endl
;
561 seen_library_macro_files_names
.insert (tail_part
);
565 clog
<< _F("Processing tapset \"%s\"", globbuf
.gl_pathv
[j
]) << endl
;
567 stapfile
* f
= parse_library_macros (s
, globbuf
.gl_pathv
[j
]);
569 s
.print_warning(_F("macro tapset \"%s\" has errors, and will be skipped.", string(globbuf
.gl_pathv
[j
]).c_str()));
571 s
.library_files
.push_back (f
);
574 unsigned next_s_library_files
= s
.library_files
.size();
575 if (s
.verbose
>1 && globbuf
.gl_pathc
> 0)
576 //TRANSLATORS: Searching through directories, 'processed' means 'examined so far'
577 clog
<< _F("Searched for library macro files: \"%s\", found: %zu, processed: %u",
578 dir
.c_str(), globbuf
.gl_pathc
,
579 (next_s_library_files
-prev_s_library_files
)) << endl
;
585 // Next, gather and parse the library files.
586 set
<pair
<dev_t
, ino_t
> > seen_library_files
;
587 set
<string
> seen_library_files_names
;
589 for (unsigned i
=0; i
<s
.include_path
.size(); i
++)
591 unsigned tapset_flags
= pf_guru
| pf_squash_errors
;
593 // The first path is special, as it's the builtin tapset.
594 // Allow all features no matter what s.compatible says.
596 tapset_flags
|= pf_no_compatible
;
598 // now iterate upon it
599 for (unsigned k
=0; k
<version_suffixes
.size(); k
++)
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
)
606 // GLOB_NOMATCH is acceptable
608 unsigned prev_s_library_files
= s
.library_files
.size();
610 for (unsigned j
=0; j
<globbuf
.gl_pathc
; j
++)
612 assert_no_interrupts();
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
)
621 << _F("usage error: tapset file '%s' cannot be run directly as a session script.",
622 globbuf
.gl_pathv
[j
]) << endl
;
626 // PR11949: duplicate-eliminate tapset files
629 pair
<dev_t
,ino_t
> here
= make_pair(tapset_file_stat
.st_dev
,
630 tapset_file_stat
.st_ino
);
631 if (seen_library_files
.find(here
) != seen_library_files
.end()) {
633 clog
<< _F("Skipping tapset \"%s\", duplicate inode.", globbuf
.gl_pathv
[j
]) << endl
;
636 seen_library_files
.insert (here
);
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()) {
646 clog
<< _F("Skipping tapset \"%s\", duplicate name.", globbuf
.gl_pathv
[j
]) << endl
;
649 seen_library_files_names
.insert (tail_part
);
653 clog
<< _F("Processing tapset \"%s\"", globbuf
.gl_pathv
[j
]) << endl
;
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.
660 stapfile
* f
= parse (s
, globbuf
.gl_pathv
[j
], tapset_flags
);
662 s
.print_warning(_F("tapset \"%s\" has errors, and will be skipped", string(globbuf
.gl_pathv
[j
]).c_str()));
664 s
.library_files
.push_back (f
);
667 unsigned next_s_library_files
= s
.library_files
.size();
668 if (s
.verbose
>1 && globbuf
.gl_pathc
> 0)
669 //TRANSLATORS: Searching through directories, 'processed' means 'examined so far'
670 clog
<< _F("Searched: \"%s\", found: %zu, processed: %u",
671 dir
.c_str(), globbuf
.gl_pathc
,
672 (next_s_library_files
-prev_s_library_files
)) << endl
;
674 globfree (& globbuf
);
680 // PASS 1b: PARSING USER SCRIPT
681 PROBE1(stap
, pass1b__start
, &s
);
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
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
)
691 unsigned user_flags
= s
.guru_mode
? pf_guru
: 0;
692 if (s
.script_file
== "-")
694 s
.user_files
.push_back (parse (s
, "<input>", cin
, user_flags
));
696 else if (s
.script_file
!= "")
698 s
.user_files
.push_back (parse (s
, s
.script_file
, user_flags
));
700 else if (s
.cmdline_script
!= "")
702 istringstream
ii (s
.cmdline_script
);
703 s
.user_files
.push_back(parse (s
, "<input>", ii
, user_flags
));
707 istringstream
ii ("probe " + s
.dump_matched_pattern
+ " {}");
708 s
.user_files
.push_back (parse (s
, "<input>", ii
, user_flags
));
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.
716 for (vector
<string
>::iterator script
= s
.additional_scripts
.begin(); script
!= s
.additional_scripts
.end(); script
++)
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
));
724 for(vector
<stapfile
*>::iterator it
= s
.user_files
.begin(); it
!= s
.user_files
.end(); it
++)
728 // Syntax errors already printed.
734 // Dump a list of probe aliases picked up, if requested
735 if (s
.dump_mode
== systemtap_session::dump_probe_aliases
)
738 vector
<stapfile
*>::const_iterator file
;
739 for (file
= s
.library_files
.begin();
740 file
!= s
.library_files
.end(); ++file
)
742 vector
<probe_alias
*>::const_iterator alias
;
743 for (alias
= (*file
)->aliases
.begin();
744 alias
!= (*file
)->aliases
.end(); ++alias
)
747 (*alias
)->printsig(ss
);
748 string str
= ss
.str();
749 if (!s
.verbose
&& startswith(str
, "_"))
755 set
<string
>::iterator alias
;
756 for (alias
= aliases
.begin();
757 alias
!= aliases
.end(); ++alias
)
759 cout
<< *alias
<< endl
;
762 // Dump the parse tree if this is the last pass
763 else if (rc
== 0 && s
.last_pass
== 1)
765 cout
<< _("# parse tree dump") << endl
;
766 for (vector
<stapfile
*>::iterator it
= s
.user_files
.begin(); it
!= s
.user_files
.end(); it
++)
770 for (unsigned i
=0; i
<s
.library_files
.size(); i
++)
772 s
.library_files
[i
]->print (cout
);
777 struct tms tms_after
;
779 unsigned _sc_clk_tck
= sysconf (_SC_CLK_TCK
);
780 struct timeval tv_after
;
781 gettimeofday (&tv_after
, NULL
);
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."
791 // syntax errors, if any, are already printed
794 // XXX also include a count of helper macro files loaded (.stpm)?
795 int n
= int(s
.library_files
.size());
796 clog
<< _("Pass 1: parsed user script and ")
797 << _NF("%d library script ", "%d library scripts ", n
, n
)
803 if (rc
&& !s
.dump_mode
)
804 cerr
<< _("Pass 1: parse failed. [man error::pass1]") << endl
;
806 PROBE1(stap
, pass1__end
, &s
);
808 assert_no_interrupts();
809 if (rc
|| s
.last_pass
== 1 ||
810 s
.dump_mode
== systemtap_session::dump_probe_aliases
)
813 times (& tms_before
);
814 gettimeofday (&tv_before
, NULL
);
816 // PASS 2: ELABORATION
817 s
.verbose
= s
.perpass_verbose
[1];
818 PROBE1(stap
, pass2__start
, &s
);
819 rc
= semantic_pass (s
);
821 // Dump a list of known probe point types, if requested.
822 if (s
.dump_mode
== systemtap_session::dump_probe_types
)
823 s
.pattern_root
->dump (s
);
824 // Dump a list of functions we picked up, if requested.
825 else if (s
.dump_mode
== systemtap_session::dump_functions
)
827 map
<string
,functiondecl
*>::const_iterator func
;
828 for (func
= s
.functions
.begin();
829 func
!= s
.functions
.end(); ++func
)
831 functiondecl
& curfunc
= *func
->second
;
832 if (curfunc
.synthetic
)
834 if (!startswith(curfunc
.name
, "__global_"))
836 if (!s
.verbose
&& startswith(curfunc
.name
, "__global__"))
838 curfunc
.printsigtags(cout
, s
.verbose
>0 /* all_tags */ );
842 // Dump the whole script if requested, or if we stop at 2
843 else if (s
.dump_mode
== systemtap_session::dump_matched_probes
||
844 s
.dump_mode
== systemtap_session::dump_matched_probes_vars
||
845 (rc
== 0 && s
.last_pass
== 2))
846 printscript(s
, cout
);
849 gettimeofday (&tv_after
, NULL
);
852 int np
= s
.probes
.size();
853 int nf
= s
.functions
.size();
854 int ne
= s
.embeds
.size();
855 int ng
= s
.globals
.size();
856 clog
<< _("Pass 2: analyzed script: ")
857 << _NF("%d probe, ", "%d probes, ", np
, np
)
858 << _NF("%d function, ", "%d functions, ", nf
, nf
)
859 << _NF("%d embed, ", "%d embeds, ", ne
, ne
)
860 << _NF("%d global ", "%d globals ", ng
, ng
)
866 if (rc
&& !s
.dump_mode
&& !s
.try_server ())
867 cerr
<< _("Pass 2: analysis failed. [man error::pass2]") << endl
;
869 PROBE1(stap
, pass2__end
, &s
);
871 assert_no_interrupts();
872 // NB: none of the dump modes need to go beyond pass-2. If this changes, break
873 // into individual modes here.
874 if (rc
|| s
.last_pass
== 2 || s
.dump_mode
)
877 rc
= prepare_translate_pass (s
);
878 assert_no_interrupts();
881 // Generate hash. There isn't any point in generating the hash
882 // if last_pass is 2, since we'll quit before using it.
883 if (s
.use_script_cache
)
886 unsigned saved_verbose
;
889 // Make sure we're in verbose mode, so that printscript()
890 // will output function/probe bodies.
891 saved_verbose
= s
.verbose
;
893 printscript(s
, o
); // Print script to 'o'
894 s
.verbose
= saved_verbose
;
898 find_script_hash (s
, o
.str());
900 // See if we can use cached source/module.
901 if (get_script_from_cache(s
))
903 // We may still need to build uprobes, if it's not also cached.
905 rc
= uprobes_pass(s
);
907 // If our last pass isn't 5, we're done (since passes 3 and
908 // 4 just generate what we just pulled out of the cache).
909 assert_no_interrupts();
910 if (rc
|| s
.last_pass
< 5) return rc
;
912 // Short-circuit to pass 5.
917 // PASS 3: TRANSLATION
918 s
.verbose
= s
.perpass_verbose
[2];
919 times (& tms_before
);
920 gettimeofday (&tv_before
, NULL
);
921 PROBE1(stap
, pass3__start
, &s
);
923 rc
= translate_pass (s
);
924 if (! rc
&& s
.last_pass
== 3)
926 ifstream
i (s
.translated_source
.c_str());
931 gettimeofday (&tv_after
, NULL
);
934 clog
<< _("Pass 3: translated to C into \"")
935 << s
.translated_source
941 if (rc
&& ! s
.try_server ())
942 cerr
<< _("Pass 3: translation failed. [man error::pass3]") << endl
;
944 PROBE1(stap
, pass3__end
, &s
);
946 assert_no_interrupts();
947 if (rc
|| s
.last_pass
== 3) return rc
;
949 // PASS 4: COMPILATION
950 s
.verbose
= s
.perpass_verbose
[3];
951 times (& tms_before
);
952 gettimeofday (&tv_before
, NULL
);
953 PROBE1(stap
, pass4__start
, &s
);
957 find_stapconf_hash(s
);
958 get_stapconf_from_cache(s
);
960 rc
= compile_pass (s
);
961 if (! rc
&& s
.last_pass
== 4)
963 cout
<< ((s
.hash_path
== "") ? s
.module_filename() : s
.hash_path
);
968 gettimeofday (&tv_after
, NULL
);
970 if (s
.verbose
) clog
<< _("Pass 4: compiled C into \"")
971 << s
.module_filename()
976 if (rc
&& ! s
.try_server ())
977 cerr
<< _("Pass 4: compilation failed. [man error::pass4]") << endl
;
981 // Update cache. Cache cleaning is kicked off at the beginning of this function.
982 if (s
.use_script_cache
)
983 add_script_to_cache(s
);
984 if (s
.use_cache
&& !s
.runtime_usermode_p())
985 add_stapconf_to_cache(s
);
987 // We may need to save the module in $CWD if the cache was
988 // inaccessible for some reason.
989 if (! s
.use_script_cache
&& s
.last_pass
== 4)
990 s
.save_module
= true;
992 // Copy module to the current directory.
993 if (s
.save_module
&& !pending_interrupts
)
995 string module_src_path
= s
.tmpdir
+ "/" + s
.module_filename();
996 string module_dest_path
= s
.module_filename();
997 copy_file(module_src_path
, module_dest_path
, s
.verbose
> 1);
1000 // Copy uprobes module to the current directory.
1001 if (s
.save_uprobes
&& !s
.uprobes_path
.empty() && !pending_interrupts
)
1003 rc
= create_dir("uprobes");
1005 copy_file(s
.uprobes_path
, "uprobes/uprobes.ko", s
.verbose
> 1);
1009 PROBE1(stap
, pass4__end
, &s
);
1015 pass_5 (systemtap_session
&s
, vector
<remote
*> targets
)
1018 s
.verbose
= s
.perpass_verbose
[4];
1019 struct tms tms_before
;
1020 times (& tms_before
);
1021 struct timeval tv_before
;
1022 gettimeofday (&tv_before
, NULL
);
1023 // NB: this message is a judgement call. The other passes don't emit
1024 // a "hello, I'm starting" message, but then the others aren't interactive
1025 // and don't take an indefinite amount of time.
1026 PROBE1(stap
, pass5__start
, &s
);
1027 if (s
.verbose
) clog
<< _("Pass 5: starting run.") << endl
;
1028 int rc
= remote::run(targets
);
1029 struct tms tms_after
;
1030 times (& tms_after
);
1031 unsigned _sc_clk_tck
= sysconf (_SC_CLK_TCK
);
1032 struct timeval tv_after
;
1033 gettimeofday (&tv_after
, NULL
);
1034 if (s
.verbose
) clog
<< _("Pass 5: run completed ")
1039 cerr
<< _("Pass 5: run failed. [man error::pass5]") << endl
;
1041 // Interrupting pass-5 to quit is normal, so we want an EXIT_SUCCESS below.
1042 pending_interrupts
= 0;
1044 PROBE1(stap
, pass5__end
, &s
);
1050 cleanup (systemtap_session
&s
, int rc
)
1052 // PASS 6: cleaning up
1053 PROBE1(stap
, pass6__start
, &s
);
1055 for (systemtap_session::session_map_t::iterator it
= s
.subsessions
.begin();
1056 it
!= s
.subsessions
.end(); ++it
)
1057 cleanup (*it
->second
, rc
);
1059 // update the database information
1060 if (!rc
&& s
.tapset_compile_coverage
&& !pending_interrupts
) {
1061 #ifdef HAVE_LIBSQLITE3
1062 update_coverage_db(s
);
1064 cerr
<< _("Coverage database not available without libsqlite3") << endl
;
1068 s
.report_suppression();
1070 PROBE1(stap
, pass6__end
, &s
);
1074 passes_0_4_again_with_server (systemtap_session
&s
)
1076 // Not a server and not already using a server.
1077 assert (! s
.client_options
);
1078 assert (s
.specified_servers
.empty ());
1080 // Specify default server(s).
1081 s
.specified_servers
.push_back ("");
1083 // Reset the previous temporary directory and start fresh
1086 // Try to compile again, using the server
1087 clog
<< _("Attempting compilation using a compile server")
1090 int rc
= passes_0_4 (s
);
1095 main (int argc
, char * const argv
[])
1097 // Initialize defaults.
1099 systemtap_session s
;
1101 setlocale (LC_ALL
, "");
1102 bindtextdomain (PACKAGE
, LOCALEDIR
);
1103 textdomain (PACKAGE
);
1106 // Set up our handler to catch routine signals, to allow clean
1107 // and reasonably timely exit.
1108 setup_signals(&handle_interrupt
);
1110 // PR13520: Parse $SYSTEMTAP_DIR/rc for extra options
1111 string rc_file
= s
.data_path
+ "/rc";
1112 ifstream
rcf (rc_file
.c_str());
1115 memset (& words
, 0, sizeof(words
));
1118 while (getline (rcf
, rcline
))
1120 rc
= wordexp (rcline
.c_str(), & words
, WRDE_NOCMD
|WRDE_UNDEF
|
1121 (linecount
> 0 ? WRDE_APPEND
: 0));
1122 // NB: WRDE_APPEND automagically reallocates words.* as more options are added.
1126 int extended_argc
= words
.we_wordc
+ argc
;
1127 char **extended_argv
= (char**) calloc (extended_argc
+ 1, sizeof(char*));
1128 if (rc
|| !extended_argv
)
1130 clog
<< _F("Error processing extra options in %s", rc_file
.c_str());
1131 return EXIT_FAILURE
;
1133 // Copy over the arguments *by reference*, first the ones from the rc file.
1134 char **p
= & extended_argv
[0];
1136 for (unsigned i
=0; i
<words
.we_wordc
; i
++) *p
++ = words
.we_wordv
[i
];
1137 for (int j
=1; j
<argc
; j
++) *p
++ = argv
[j
];
1140 // Process the command line.
1141 rc
= s
.parse_cmdline (extended_argc
, extended_argv
);
1145 if (words
.we_wordc
> 0 && s
.verbose
> 1)
1146 clog
<< _F("Extra options in %s: %d\n", rc_file
.c_str(), (int)words
.we_wordc
);
1148 // Check for options conflicts. Exits if errors are detected.
1149 s
.check_options (extended_argc
, extended_argv
);
1151 // We don't need these strings any more.
1153 free (extended_argv
);
1155 // arguments parsed; get down to business
1159 // Need to send the verbose message here, rather than in the session ctor, since
1160 // we didn't know if verbose was set.
1161 if (rc
== 0 && s
.verbose
>1)
1162 clog
<< _F("Created temporary directory \"%s\"", s
.tmpdir
.c_str()) << endl
;
1164 // Run the benchmark and quit right away.
1165 if (s
.benchmark_sdt_loops
|| s
.benchmark_sdt_threads
)
1166 return run_sdt_benchmark(s
);
1168 // Prepare connections for each specified remote target.
1169 vector
<remote
*> targets
;
1170 bool fake_remote
=false;
1171 if (s
.remote_uris
.empty())
1174 s
.remote_uris
.push_back("direct:");
1176 for (unsigned i
= 0; rc
== 0 && i
< s
.remote_uris
.size(); ++i
)
1178 // PR13354: pass remote id#/url only in non --remote=HOST cases
1179 remote
*target
= remote::create(s
, s
.remote_uris
[i
],
1180 fake_remote
? -1 : (int)i
);
1182 targets
.push_back(target
);
1187 // Discover and loop over each unique session created by the remote targets.
1188 set
<systemtap_session
*> sessions
;
1189 for (unsigned i
= 0; i
< targets
.size(); ++i
)
1190 sessions
.insert(targets
[i
]->get_session());
1191 for (set
<systemtap_session
*>::iterator it
= sessions
.begin();
1192 rc
== 0 && !pending_interrupts
&& it
!= sessions
.end(); ++it
)
1194 systemtap_session
& ss
= **it
;
1196 clog
<< _F("Session arch: %s release: %s",
1197 ss
.architecture
.c_str(), ss
.kernel_release
.c_str()) << endl
;
1200 // If requested, query server status. This is independent of other tasks.
1201 query_server_status (ss
);
1203 // If requested, manage trust of servers. This is independent of other tasks.
1204 manage_server_trust (ss
);
1207 // Run the passes only if a script has been specified or if we're
1208 // dumping something. The requirement for a script has already been
1209 // checked in systemtap_session::check_options.
1210 if (ss
.have_script
|| ss
.dump_mode
)
1212 // Run passes 0-4 for each unique session,
1213 // either locally or using a compile-server.
1214 ss
.init_try_server ();
1215 if ((rc
= passes_0_4 (ss
)))
1217 // Compilation failed.
1218 // Try again using a server if appropriate.
1219 if (ss
.try_server ())
1220 rc
= passes_0_4_again_with_server (ss
);
1222 if (rc
|| s
.perpass_verbose
[0] >= 1)
1223 s
.explain_auto_options ();
1227 // Run pass 5, if requested
1228 if (rc
== 0 && s
.have_script
&& s
.last_pass
>= 5 && ! pending_interrupts
)
1229 rc
= pass_5 (s
, targets
);
1232 for (unsigned i
= 0; i
< targets
.size(); ++i
)
1236 assert_no_interrupts();
1237 return (rc
) ? EXIT_FAILURE
: EXIT_SUCCESS
;
1239 catch (const interrupt_exception
& e
) {
1240 // User entered ctrl-c, exit quietly.
1241 return EXIT_FAILURE
;
1243 catch (const exit_exception
& e
) {
1244 // Exiting for any quiet reason.
1247 catch (const exception
&e
) {
1248 // Some other uncaught exception.
1249 cerr
<< e
.what() << endl
;
1250 return EXIT_FAILURE
;
1253 // Catch all other unknown exceptions.
1254 cerr
<< _("ERROR: caught unknown exception!") << endl
;
1255 return EXIT_FAILURE
;
1259 /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */