1 // systemtap translator/driver
2 // Copyright (C) 2005-2019 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"
26 #include "client-nss.h"
29 #include "setupdwfl.h"
30 #ifdef HAVE_LIBREADLINE
31 #include "interactive.h"
33 #if HAVE_LANGUAGE_SERVER_SUPPORT
34 #include "language-server/stap-language-server.h"
44 #include "stap-probe.h"
54 #include <sys/utsname.h>
55 #include <sys/times.h>
69 uniq_list(list
<string
>& l
)
72 list
<string
>::iterator i
= l
.begin();
74 if (s
.insert(*i
).second
)
81 printscript(systemtap_session
& s
, ostream
& o
)
83 if (s
.dump_mode
== systemtap_session::dump_matched_probes
||
84 s
.dump_mode
== systemtap_session::dump_matched_probes_vars
)
86 // We go through some heroic measures to produce clean output.
87 // Record the alias and probe pointer as <name, set<derived_probe *> >
88 map
<string
,set
<derived_probe
*> > probe_list
;
90 // Pre-process the probe alias
91 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
93 assert_no_interrupts();
95 derived_probe
* p
= s
.probes
[i
];
97 p
->collect_derivation_chain (chain
);
100 p
->printsig(cerr
); cerr
<< endl
;
101 cerr
<< "chain[" << chain
.size() << "]:" << endl
;
102 for (unsigned j
=0; j
<chain
.size(); j
++)
104 cerr
<< " [" << j
<< "]: " << endl
;
105 cerr
<< "\tlocations[" << chain
[j
]->locations
.size() << "]:" << endl
;
106 for (unsigned k
=0; k
<chain
[j
]->locations
.size(); k
++)
108 cerr
<< "\t [" << k
<< "]: ";
109 chain
[j
]->locations
[k
]->print(cerr
);
112 const probe_alias
*a
= chain
[j
]->get_alias();
115 cerr
<< "\taliases[" << a
->alias_names
.size() << "]:" << endl
;
116 for (unsigned k
=0; k
<a
->alias_names
.size(); k
++)
118 cerr
<< "\t [" << k
<< "]: ";
119 a
->alias_names
[k
]->print(cerr
);
126 const string
& pp
= lex_cast(*p
->script_location());
128 // PR16730: We should only list probes that can be traced back to the
129 // user's spec, not any auxiliary probes in the tapsets.
130 // Also, do not want to the probes that are from the additional
131 // scripts (-E SCRIPT) to be listed.
132 if (!s
.is_primary_probe(p
))
135 // Now duplicate-eliminate. An alias may have expanded to
136 // several actual derived probe points, but we only want to
137 // print the alias head name once.
138 probe_list
[pp
].insert(p
);
141 // print probe name and variables if there
142 for (map
<string
, set
<derived_probe
*> >::iterator it
=probe_list
.begin(); it
!=probe_list
.end(); ++it
)
146 // probe name or alias
147 if (s
.dump_mode
== systemtap_session::dump_matched_probes_vars
&& isatty(STDOUT_FILENO
))
148 pp
= s
.colorize(it
->first
, "source");
152 // Print the locals and arguments for -L mode only
153 if (s
.dump_mode
== systemtap_session::dump_matched_probes_vars
)
155 map
<string
,unsigned> var_count
; // format <"name:type",count>
156 map
<string
,unsigned> arg_count
;
157 list
<string
> var_list
;
158 list
<string
> arg_list
;
159 // traverse set<derived_probe *> to collect all locals and arguments
160 for (set
<derived_probe
*>::iterator ix
=it
->second
.begin(); ix
!=it
->second
.end(); ++ix
)
162 derived_probe
* p
= *ix
;
163 // collect available locals of the probe
164 for (unsigned j
=0; j
<p
->locals
.size(); j
++)
167 vardecl
* v
= p
->locals
[j
];
169 var_count
[tmps
.str()]++;
170 var_list
.push_back(tmps
.str());
172 // collect arguments of the probe if there
173 list
<string
> arg_set
;
175 for (list
<string
>::iterator ia
=arg_set
.begin(); ia
!=arg_set
.end(); ++ia
) {
177 arg_list
.push_back(*ia
);
180 // If verbosity is set, we want to print out all instances of duplicated probes and
181 // distinguish them with the PC address.
184 // We want to print the probe point signature (without the nested components).
185 std::ostringstream sig
;
186 p
->printsig_nonest(sig
);
188 p
->printsig_nested(sig
);
190 if (s
.dump_mode
== systemtap_session::dump_matched_probes_vars
&& isatty(STDOUT_FILENO
))
191 o
<< s
.colorize(sig
.str(), "source");
195 for (list
<string
>::iterator ir
=var_list
.begin(); ir
!=var_list
.end(); ++ir
)
197 for (list
<string
>::iterator ir
=arg_list
.begin(); ir
!=arg_list
.end(); ++ir
)
207 if (!(s
.verbose
> 0))
214 // print the set-intersection only
215 for (list
<string
>::iterator ir
=var_list
.begin(); ir
!=var_list
.end(); ++ir
)
216 if (var_count
.find(*ir
)->second
== it
->second
.size()) // print locals
218 for (list
<string
>::iterator ir
=arg_list
.begin(); ir
!=arg_list
.end(); ++ir
)
219 if (arg_count
.find(*ir
)->second
== it
->second
.size()) // print arguments
234 if (s
.embeds
.size() > 0)
235 o
<< _("# global embedded code") << endl
;
236 for (unsigned i
=0; i
<s
.embeds
.size(); i
++)
238 assert_no_interrupts();
239 embeddedcode
* ec
= s
.embeds
[i
];
244 if (s
.globals
.size() > 0)
245 o
<< _("# globals") << endl
;
246 for (unsigned i
=0; i
<s
.globals
.size(); i
++)
248 assert_no_interrupts();
249 vardecl
* v
= s
.globals
[i
];
251 if (s
.verbose
&& v
->init
)
259 if (s
.functions
.size() > 0)
260 o
<< _("# functions") << endl
;
261 for (map
<string
,functiondecl
*>::iterator it
= s
.functions
.begin(); it
!= s
.functions
.end(); it
++)
263 assert_no_interrupts();
264 functiondecl
* f
= it
->second
;
267 if (f
->locals
.size() > 0)
268 o
<< _(" # locals") << endl
;
269 for (unsigned j
=0; j
<f
->locals
.size(); j
++)
271 vardecl
* v
= f
->locals
[j
];
284 if (s
.probes
.size() > 0)
285 o
<< _("# probes") << endl
;
286 for (unsigned i
=0; i
<s
.probes
.size(); i
++)
288 assert_no_interrupts();
289 derived_probe
* p
= s
.probes
[i
];
292 if (p
->locals
.size() > 0)
293 o
<< _(" # locals") << endl
;
294 for (unsigned j
=0; j
<p
->locals
.size(); j
++)
296 vardecl
* v
= p
->locals
[j
];
312 int pending_interrupts
;
315 void handle_interrupt (int)
317 // This might be nice, but we don't know our current verbosity...
318 // clog << _F("Received signal %d", sig) << endl << flush;
319 kill_stap_spawn(SIGTERM
);
321 pending_interrupts
++;
322 // Absorb the first two signals. This used to be one, but when
323 // stap is run under sudo, and then interrupted, sudo relays a
324 // redundant copy of the signal to stap, leading to an unclean shutdown.
325 if (pending_interrupts
> 2) // XXX: should be configurable? time-based?
327 char msg
[] = "Too many interrupts received, exiting.\n";
330 /* NB: writing to stderr blockingly in a signal handler is dangerous
331 * since it may prevent the stap process from quitting gracefully
332 * on receiving SIGTERM/etc signals when the stderr write buffer
333 * is full. PR23891 */
334 int flags
= fcntl(fd
, F_GETFL
);
338 if (!(flags
& O_NONBLOCK
))
340 if (fcntl(fd
, F_SETFL
, flags
| O_NONBLOCK
) == 0) {
341 int rc
= write (fd
, msg
, sizeof(msg
)-1);
344 /* Do nothing; we don't care if our last gasp went out. */
348 } /* if ! O_NONBLOCK */
350 /* to avoid leaving any side-effects on the stderr device */
351 (void) fcntl(fd
, F_SETFL
, flags
& ~O_NONBLOCK
);
358 setup_signals (sighandler_t handler
)
362 memset(&sa
, 0, sizeof(sa
));
363 sa
.sa_handler
= handler
;
364 sigemptyset (&sa
.sa_mask
);
365 if (handler
!= SIG_IGN
)
367 sigaddset (&sa
.sa_mask
, SIGHUP
);
368 sigaddset (&sa
.sa_mask
, SIGPIPE
);
369 sigaddset (&sa
.sa_mask
, SIGINT
);
370 sigaddset (&sa
.sa_mask
, SIGTERM
);
371 sigaddset (&sa
.sa_mask
, SIGXFSZ
);
372 sigaddset (&sa
.sa_mask
, SIGXCPU
);
374 sa
.sa_flags
= SA_RESTART
;
376 sigaction (SIGHUP
, &sa
, NULL
);
377 sigaction (SIGPIPE
, &sa
, NULL
);
378 sigaction (SIGINT
, &sa
, NULL
);
379 sigaction (SIGTERM
, &sa
, NULL
);
380 sigaction (SIGXFSZ
, &sa
, NULL
);
381 sigaction (SIGXCPU
, &sa
, NULL
);
386 sdt_benchmark_thread(unsigned long i
, double fp1
, float fp2
)
388 PROBE(stap
, benchmark__thread__start
);
391 double fp_local1
= 1.01;
392 float fp_local2
= 2.02;
393 PROBE2(stap
, benchmark__fp
, fp1
+fp_local1
, fp2
+fp_local2
);
394 double fp_local3
= 3.03;
395 double fp_local4
= 4.04;
396 double fp_local5
= 5.05;
397 double fp_local6
= 6.06;
398 double fp_local7
= 7.07;
399 double fp_local8
= 8.08;
400 double fp_local9
= 9.09;
401 double fp_local10
= 10.01;
402 double fp_local11
= 11.01;
403 double fp_local12
= 12.01;
404 double fp_local13
= 13.01;
405 double fp_local14
= 14.01;
406 double fp_local15
= 15.01;
423 PROBE1(stap
, benchmark
, i
);
424 PROBE(stap
, benchmark__thread__end
);
429 run_sdt_benchmark(systemtap_session
& s
)
431 unsigned long loops
= s
.benchmark_sdt_loops
?: 10000000;
432 unsigned long threads
= s
.benchmark_sdt_threads
?: 1;
435 clog
<< _F("Beginning SDT benchmark with %lu loops in %lu threads.",
436 loops
, threads
) << endl
;
438 struct tms tms_before
, tms_after
;
439 struct timeval tv_before
, tv_after
;
440 unsigned _sc_clk_tck
= sysconf (_SC_CLK_TCK
);
441 times (& tms_before
);
442 gettimeofday (&tv_before
, NULL
);
444 PROBE(stap
, benchmark__start
);
446 vector
<thread
> handles
;
449 for (unsigned long i
= 0; i
< threads
; ++i
)
450 handles
.push_back(thread(sdt_benchmark_thread
, loops
, f
, f2
));
451 for (unsigned long i
= 0; i
< threads
; ++i
)
454 PROBE(stap
, benchmark__end
);
457 gettimeofday (&tv_after
, NULL
);
459 clog
<< _F("Completed SDT benchmark in %ldusr/%ldsys/%ldreal ms.",
460 (long)(tms_after
.tms_utime
- tms_before
.tms_utime
) * 1000 / _sc_clk_tck
,
461 (long)(tms_after
.tms_stime
- tms_before
.tms_stime
) * 1000 / _sc_clk_tck
,
462 (long)((tv_after
.tv_sec
- tv_before
.tv_sec
) * 1000 +
463 ((long)tv_after
.tv_usec
- (long)tv_before
.tv_usec
) / 1000))
469 static set
<string
> files
;
470 static string path_dir
;
472 static int collect_stp(const char* fpath
, const struct stat
*,
473 int typeflag
, struct FTW
* ftwbuf
)
475 if (typeflag
== FTW_F
)
477 const char* ext
= strrchr(fpath
, '.');
478 if (ext
&& (strcmp(".stp", ext
) == 0))
481 else if (typeflag
== FTW_D
&& ftwbuf
->level
> 0)
483 // Only recurse for PATH root directory
484 if (strncmp(path_dir
.c_str(), fpath
, path_dir
.size()) != 0 ||
485 (fpath
[path_dir
.size()] != '/' && fpath
[path_dir
.size()] != '\0'))
486 return FTW_SKIP_SUBTREE
;
491 static int collect_stpm(const char* fpath
, const struct stat
*,
492 int typeflag
, struct FTW
* ftwbuf
)
494 if (typeflag
== FTW_F
)
496 const char* ext
= strrchr(fpath
, '.');
497 if (ext
&& (strcmp(".stpm", ext
) == 0))
500 else if (typeflag
== FTW_D
&& ftwbuf
->level
> 0)
502 // Only recurse for PATH root directory
503 if (strncmp(path_dir
.c_str(), fpath
, path_dir
.size()) != 0 ||
504 (fpath
[path_dir
.size()] != '/' && fpath
[path_dir
.size()] != '\0'))
505 return FTW_SKIP_SUBTREE
;
512 translate_bpf_pass (systemtap_session
&)
518 // Compilation passes 0 through 4
520 passes_0_4 (systemtap_session
&s
)
524 // If we don't know the release, there's no hope either locally or on a server.
525 if (s
.kernel_release
.empty())
527 if (s
.kernel_build_tree
.empty())
528 cerr
<< _("ERROR: kernel release isn't specified") << endl
;
530 cerr
<< _F("ERROR: kernel release isn't found in \"%s\"",
531 s
.kernel_build_tree
.c_str()) << endl
;
535 // Perform passes 0 through 4 using a compile server?
536 if (! s
.specified_servers
.empty ())
538 #if NEED_BASE_CLIENT_CODE
539 compile_server_client
client (s
);
540 return client
.passes_0_4 ();
542 s
.print_warning(_("Without NSS or HTTP client support, using a compile-server is not supported by this version of systemtap"));
544 // This cannot be an attempt to use a server after a local compile failed
545 // since --use-server-on-error is locked to 'no' if we don't have
547 assert (! s
.try_server ());
548 s
.print_warning(_("Ignoring --use-server"));
552 // PASS 0: setting up
553 s
.verbose
= s
.perpass_verbose
[0];
554 PROBE1(stap
, pass0__start
, &s
);
556 // For PR1477, we used to override $PATH and $LC_ALL and other stuff
557 // here. We seem to use complete pathnames in
558 // buildrun.cxx/tapsets.cxx now, so this is not necessary. Further,
559 // it interferes with util.cxx:find_executable(), used for $PATH
562 s
.kernel_base_release
.assign(s
.kernel_release
, 0, s
.kernel_release
.find('-'));
564 // Update various paths to include the sysroot, if provided.
565 if (!s
.sysroot
.empty())
567 if (s
.update_release_sysroot
&& !s
.sysroot
.empty())
568 s
.kernel_build_tree
= s
.sysroot
+ s
.kernel_build_tree
;
569 debuginfo_path_insert_sysroot(s
.sysroot
);
572 // Now that no further changes to s.kernel_build_tree can occur, let's use it.
573 if (!s
.runtime_usermode_p())
575 if ((rc
= s
.parse_kernel_config ()) != 0
576 || (rc
= s
.parse_kernel_exports ()) != 0
577 || (rc
= s
.parse_kernel_functions ()) != 0)
579 // Try again with a server
585 // Create the name of the main C source file within the temporary
586 // directory. Note the _src prefix, explained in
587 // buildrun.cxx:compile_pass()
588 s
.translated_source
= string(s
.tmpdir
) + "/" + s
.module_name
+ "_src.c";
590 // Create the name of the C source file for the dumped symbol data
591 // within the temporary directory. This file will be generated in
592 // translate.cxx:emit_symbol_data()
593 s
.symbols_source
= string(s
.tmpdir
) + "/stap_symbols.c";
595 PROBE1(stap
, pass0__end
, &s
);
597 struct tms tms_before
;
598 times (& tms_before
);
599 struct timeval tv_before
;
600 gettimeofday (&tv_before
, NULL
);
602 // PASS 1a: PARSING LIBRARY SCRIPTS
603 PROBE1(stap
, pass1a__start
, &s
);
605 // prep this array for tapset $n use too ... although we will reset once again for user scripts
606 s
.used_args
.resize(s
.args
.size(), false);
608 if (! s
.pass_1a_complete
)
610 // We need to handle the library scripts first because this pass
611 // gathers information on .stpm files that might be needed to
612 // parse the user script.
614 // We need to first ascertain the status of the user script, though.
615 struct stat user_file_stat
;
616 int user_file_stat_rc
= -1;
618 if (s
.script_file
== "-")
620 user_file_stat_rc
= fstat (STDIN_FILENO
, & user_file_stat
);
622 else if (s
.script_file
!= "")
627 path_dir
= string(PKGDATADIR
) + "/examples";
628 (void) nftw(path_dir
.c_str(), collect_stp
, 1, FTW_ACTIONRETVAL
);
630 vector
<string
> examples
;
631 for (auto it
= files
.begin(); it
!= files
.end(); ++it
)
633 string::size_type last_slash_index
= it
->find_last_of('/');
634 string example_name
= it
->substr(last_slash_index
+ 1);
635 if (s
.script_file
== example_name
)
636 examples
.push_back(*it
);
639 if (examples
.size() > 1)
641 cerr
<< "Multiple examples found: " << endl
;
642 for (auto it
= examples
.begin(); it
!= examples
.end(); ++it
)
643 cerr
<< " " << *it
<< endl
;
646 else if (examples
.size() == 0)
648 cerr
<< _F("Example '%s' was not found under '%s'", s
.script_file
.c_str(), path_dir
.c_str()) << endl
;
652 s
.script_file
= examples
[0];
655 user_file_stat_rc
= stat (s
.script_file
.c_str(), & user_file_stat
);
657 // otherwise, rc is 0 for a command line script
659 vector
<string
> version_suffixes
;
660 if (!s
.runtime_usermode_p())
662 // Construct kernel-versioning search path
663 string kvr
= s
.kernel_release
;
665 // add full kernel-version-release (2.6.NN-FOOBAR)
666 version_suffixes
.push_back ("/" + kvr
);
668 // add kernel version (2.6.NN)
669 if (kvr
!= s
.kernel_base_release
)
671 kvr
= s
.kernel_base_release
;
672 version_suffixes
.push_back ("/" + kvr
);
675 // add kernel family (2.6)
676 string::size_type dot1_index
= kvr
.find ('.');
677 string::size_type dot2_index
= kvr
.rfind ('.');
678 while (dot2_index
> dot1_index
&& dot2_index
!= string::npos
)
680 kvr
.erase(dot2_index
);
681 version_suffixes
.push_back ("/" + kvr
);
682 dot2_index
= kvr
.rfind ('.');
686 // add empty string as last element
687 version_suffixes
.push_back ("");
689 // Add arch variants of every path, just before each
690 const string
& arch
= s
.architecture
;
691 for (unsigned i
=0; i
<version_suffixes
.size(); i
+=2)
692 version_suffixes
.insert(version_suffixes
.begin() + i
,
693 version_suffixes
[i
] + "/" + arch
);
695 // Add runtime variants of every path, before everything else
696 string runtime_prefix
;
697 if (s
.runtime_mode
== systemtap_session::kernel_runtime
)
698 runtime_prefix
= "/linux";
699 else if (s
.runtime_mode
== systemtap_session::dyninst_runtime
)
700 runtime_prefix
= "/dyninst";
701 else if (s
.runtime_mode
== systemtap_session::bpf_runtime
)
702 runtime_prefix
= "/bpf";
703 if (!runtime_prefix
.empty())
704 for (unsigned i
=0; i
<version_suffixes
.size(); i
+=2)
705 version_suffixes
.insert(version_suffixes
.begin() + i
/2,
706 runtime_prefix
+ version_suffixes
[i
]);
708 // First, parse .stpm files on the include path. We need to have the
709 // resulting macro definitions available for parsing library files,
710 // but since .stpm files can consist only of '@define' constructs,
711 // we can parse each one without reference to the others.
712 set
<pair
<dev_t
, ino_t
> > seen_library_macro_files
;
713 set
<string
> seen_library_macro_files_names
;
715 for (unsigned i
=0; i
<s
.include_path
.size(); i
++)
717 // now iterate upon it
718 for (unsigned k
=0; k
<version_suffixes
.size(); k
++)
720 int flags
= FTW_ACTIONRETVAL
;
721 string dir
= s
.include_path
[i
] + version_suffixes
[k
];
723 // we need to set this for the nftw() callback
724 path_dir
= s
.include_path
[i
] + "/PATH";
725 (void) nftw(dir
.c_str(), collect_stpm
, 1, flags
);
727 unsigned prev_s_library_files
= s
.library_files
.size();
729 for (auto it
= files
.begin(); it
!= files
.end(); ++it
)
731 assert_no_interrupts();
733 struct stat tapset_file_stat
;
734 int stat_rc
= stat (it
->c_str(), & tapset_file_stat
);
735 if (stat_rc
== 0 && user_file_stat_rc
== 0 &&
736 user_file_stat
.st_dev
== tapset_file_stat
.st_dev
&&
737 user_file_stat
.st_ino
== tapset_file_stat
.st_ino
)
740 << _F("usage error: macro tapset file '%s' cannot be run directly as a session script.",
741 it
->c_str()) << endl
;
745 // PR11949: duplicate-eliminate tapset files
748 pair
<dev_t
,ino_t
> here
= make_pair(tapset_file_stat
.st_dev
,
749 tapset_file_stat
.st_ino
);
750 if (seen_library_macro_files
.find(here
) != seen_library_macro_files
.end())
753 clog
<< _F("Skipping tapset \"%s\", duplicate inode.", it
->c_str()) << endl
;
756 seen_library_macro_files
.insert (here
);
759 // PR12443: duplicate-eliminate harder
760 string full_path
= *it
;
761 string tapset_base
= s
.include_path
[i
]; // not dir; it has arch suffixes too
762 if (full_path
.size() > tapset_base
.size())
764 string tail_part
= full_path
.substr(tapset_base
.size());
765 if (seen_library_macro_files_names
.find (tail_part
) != seen_library_macro_files_names
.end())
768 clog
<< _F("Skipping tapset \"%s\", duplicate name.", it
->c_str()) << endl
;
771 seen_library_macro_files_names
.insert (tail_part
);
775 clog
<< _F("Processing tapset \"%s\"", it
->c_str()) << endl
;
777 stapfile
* f
= parse_library_macros (s
, *it
);
779 s
.print_warning(_F("macro tapset \"%s\" has errors, and will be skipped.", it
->c_str()));
781 s
.library_files
.push_back (f
);
784 unsigned next_s_library_files
= s
.library_files
.size();
785 if (s
.verbose
>1 && !files
.empty())
786 //TRANSLATORS: Searching through directories, 'processed' means 'examined so far'
787 clog
<< _F("Searched for library macro files: \"%s\", found: %zu, processed: %u",
788 dir
.c_str(), files
.size(),
789 (next_s_library_files
-prev_s_library_files
)) << endl
;
793 // Next, gather and parse the library files.
794 set
<pair
<dev_t
, ino_t
> > seen_library_files
;
795 set
<string
> seen_library_files_names
;
797 for (unsigned i
=0; i
<s
.include_path
.size(); i
++)
799 // now iterate upon it
800 for (unsigned k
=0; k
<version_suffixes
.size(); k
++)
802 int flags
= FTW_ACTIONRETVAL
;
803 string dir
= s
.include_path
[i
] + version_suffixes
[k
];
805 // we need to set this for the nftw() callback
806 path_dir
= s
.include_path
[i
] + "/PATH";
807 (void) nftw(dir
.c_str(), collect_stp
, 1, flags
);
809 unsigned prev_s_library_files
= s
.library_files
.size();
811 for (auto it
= files
.begin(); it
!= files
.end(); ++it
)
813 unsigned tapset_flags
= pf_guru
| pf_squash_errors
;
815 // The first path is special, as it's the builtin tapset.
816 // Allow all features no matter what s.compatible says.
818 tapset_flags
|= pf_no_compatible
;
820 if (it
->find("/PATH/") != string::npos
)
821 tapset_flags
|= pf_auto_path
;
823 assert_no_interrupts();
825 struct stat tapset_file_stat
;
826 int stat_rc
= stat (it
->c_str(), & tapset_file_stat
);
827 if (stat_rc
== 0 && user_file_stat_rc
== 0 &&
828 user_file_stat
.st_dev
== tapset_file_stat
.st_dev
&&
829 user_file_stat
.st_ino
== tapset_file_stat
.st_ino
)
832 << _F("usage error: tapset file '%s' cannot be run directly as a session script.",
833 it
->c_str()) << endl
;
837 // PR11949: duplicate-eliminate tapset files
840 pair
<dev_t
,ino_t
> here
= make_pair(tapset_file_stat
.st_dev
,
841 tapset_file_stat
.st_ino
);
842 if (seen_library_files
.find(here
) != seen_library_files
.end())
845 clog
<< _F("Skipping tapset \"%s\", duplicate inode.", it
->c_str()) << endl
;
848 seen_library_files
.insert (here
);
851 // PR12443: duplicate-eliminate harder
852 string full_path
= *it
;
853 string tapset_base
= s
.include_path
[i
]; // not dir; it has arch suffixes too
854 if (full_path
.size() > tapset_base
.size())
856 string tail_part
= full_path
.substr(tapset_base
.size());
857 if (seen_library_files_names
.find (tail_part
) != seen_library_files_names
.end())
860 clog
<< _F("Skipping tapset \"%s\", duplicate name.", it
->c_str()) << endl
;
863 seen_library_files_names
.insert (tail_part
);
867 clog
<< _F("Processing tapset \"%s\"", it
->c_str()) << endl
;
869 // NB: we don't need to restrict privilege only for
870 // /usr/share/systemtap, i.e., excluding
871 // user-specified $XDG_DATA_DIRS. That's because
872 // stapdev gets root-equivalent privileges anyway;
873 // stapsys and stapusr use a remote compilation with
874 // a trusted environment, where client-side
875 // $XDG_DATA_DIRS are not passed.
877 stapfile
* f
= parse (s
, *it
, tapset_flags
);
879 s
.print_warning(_F("tapset \"%s\" has errors, and will be skipped", it
->c_str()));
882 assert (f
->privileged
);
883 s
.library_files
.push_back (f
);
887 unsigned next_s_library_files
= s
.library_files
.size();
888 if (s
.verbose
>1 && !files
.empty())
889 //TRANSLATORS: Searching through directories, 'processed' means 'examined so far'
890 clog
<< _F("Searched: \"%s\", found: %zu, processed: %u",
891 dir
.c_str(), files
.size(),
892 (next_s_library_files
-prev_s_library_files
)) << endl
;
899 // Now that we've made it through pass 1a, remember this so we
900 // don't have to do this again in interactive mode. This doesn't
901 // effect non-interactive mode.
902 s
.pass_1a_complete
= true;
905 // PASS 1b: PARSING USER SCRIPT
906 PROBE1(stap
, pass1b__start
, &s
);
908 // reset for user scripts -- it's their use of $* we care about
909 // except that tapsets like argv.stp can consume $parms
910 fill(s
.used_args
.begin(), s
.used_args
.end(), false);
912 // Only try to parse a user script if the user provided one, or if we have to
913 // make one (as is the case for listing mode). Otherwise, s.user_script
915 if (!s
.script_file
.empty() ||
916 !s
.cmdline_script
.empty() ||
917 s
.dump_mode
== systemtap_session::dump_matched_probes
||
918 s
.dump_mode
== systemtap_session::dump_matched_probes_vars
)
920 unsigned user_flags
= s
.guru_mode
? pf_guru
: 0;
921 user_flags
|= pf_user_file
;
922 if (s
.script_file
== "-")
924 if (s
.stdin_script
.str().empty())
925 s
.stdin_script
<< cin
.rdbuf();
926 s
.user_files
.push_back (parse (s
, "<input>", s
.stdin_script
,
929 else if (s
.script_file
!= "")
931 s
.user_files
.push_back (parse (s
, s
.script_file
, user_flags
));
933 else if (s
.cmdline_script
!= "")
935 istringstream
ii (s
.cmdline_script
);
936 s
.user_files
.push_back(parse (s
, "<input>", ii
, user_flags
));
940 istringstream
ii ("probe " + s
.dump_matched_pattern
+ " {}");
941 s
.user_files
.push_back (parse (s
, "<input>", ii
, user_flags
));
944 // parses the additional script(s) (-E script). does so even if in listing
945 // mode, incase there is something special in the additional script(s),
946 // like a macro or alias. give them a unique name to differentiate the
947 // scripts that were inputted.
949 for (vector
<string
>::iterator script
= s
.additional_scripts
.begin(); script
!= s
.additional_scripts
.end(); script
++)
951 string input_name
= "<input" + lex_cast(count
) + ">";
952 istringstream
ii (*script
);
953 s
.user_files
.push_back(parse (s
, input_name
, ii
, user_flags
));
957 for(vector
<stapfile
*>::iterator it
= s
.user_files
.begin(); it
!= s
.user_files
.end(); it
++)
961 // Syntax errors already printed.
966 else if (s
.cmdline_script
.empty() &&
967 s
.dump_mode
== systemtap_session::dump_none
) // -e ''
969 cerr
<< _("Input file '<input>' is empty.") << endl
;
973 // Dump a list of probe aliases picked up, if requested
974 if (s
.dump_mode
== systemtap_session::dump_probe_aliases
)
977 vector
<stapfile
*>::const_iterator file
;
978 for (file
= s
.library_files
.begin();
979 file
!= s
.library_files
.end(); ++file
)
981 vector
<probe_alias
*>::const_iterator alias
;
982 for (alias
= (*file
)->aliases
.begin();
983 alias
!= (*file
)->aliases
.end(); ++alias
)
986 (*alias
)->printsig(ss
);
987 string str
= ss
.str();
988 if (!s
.verbose
&& startswith(str
, "_"))
994 set
<string
>::iterator alias
;
995 for (alias
= aliases
.begin();
996 alias
!= aliases
.end(); ++alias
)
998 cout
<< *alias
<< endl
;
1001 // Dump the parse tree if this is the last pass
1002 else if (rc
== 0 && s
.last_pass
== 1)
1004 cout
<< _("# parse tree dump") << endl
;
1005 for (vector
<stapfile
*>::iterator it
= s
.user_files
.begin(); it
!= s
.user_files
.end(); it
++)
1006 (*it
)->print (cout
);
1009 for (unsigned i
=0; i
<s
.library_files
.size(); i
++)
1011 s
.library_files
[i
]->print (cout
);
1016 struct tms tms_after
;
1017 times (& tms_after
);
1018 unsigned _sc_clk_tck
= sysconf (_SC_CLK_TCK
);
1019 struct timeval tv_after
;
1020 gettimeofday (&tv_after
, NULL
);
1022 #define TIMESPRINT _("in ") << \
1023 (tms_after.tms_cutime + tms_after.tms_utime \
1024 - tms_before.tms_cutime - tms_before.tms_utime) * 1000 / (_sc_clk_tck) << "usr/" \
1025 << (tms_after.tms_cstime + tms_after.tms_stime \
1026 - tms_before.tms_cstime - tms_before.tms_stime) * 1000 / (_sc_clk_tck) << "sys/" \
1027 << ((tv_after.tv_sec - tv_before.tv_sec) * 1000 + \
1028 ((long)tv_after.tv_usec - (long)tv_before.tv_usec) / 1000) << "real ms."
1030 // syntax errors, if any, are already printed
1033 // XXX also include a count of helper macro files loaded (.stpm)?
1034 int n
= int(s
.library_files
.size());
1035 clog
<< _("Pass 1: parsed user script and ")
1036 << _NF("%d library script ", "%d library scripts ", n
, n
)
1042 if (rc
&& !s
.dump_mode
)
1043 cerr
<< _("Pass 1: parse failed. [man error::pass1]") << endl
;
1045 PROBE1(stap
, pass1__end
, &s
);
1047 assert_no_interrupts();
1048 if (rc
|| s
.last_pass
== 1 ||
1049 s
.dump_mode
== systemtap_session::dump_probe_aliases
)
1052 times (& tms_before
);
1053 gettimeofday (&tv_before
, NULL
);
1055 // PASS 2: ELABORATION
1056 s
.verbose
= s
.perpass_verbose
[1];
1057 PROBE1(stap
, pass2__start
, &s
);
1058 rc
= semantic_pass (s
);
1060 // http handled probes need probe information from pass 2
1061 if (! s
.http_servers
.empty ())
1063 #if NEED_BASE_CLIENT_CODE
1064 compile_server_client
client (s
);
1065 return client
.passes_0_4 ();
1067 s
.print_warning(_("Without NSS or HTTP client support, using a compile-server is not supported by this version of systemtap"));
1069 // This cannot be an attempt to use a server after a local compile failed
1070 // since --use-server-on-error is locked to 'no' if we don't have
1072 assert (! s
.try_server ());
1073 s
.print_warning(_("Ignoring --use-server"));
1077 // Dump a list of known probe point types, if requested.
1078 if (s
.dump_mode
== systemtap_session::dump_probe_types
)
1079 s
.pattern_root
->dump (s
);
1080 // Dump a list of functions we picked up, if requested.
1081 else if (s
.dump_mode
== systemtap_session::dump_functions
)
1083 map
<string
,functiondecl
*>::const_iterator func
;
1084 for (func
= s
.functions
.begin();
1085 func
!= s
.functions
.end(); ++func
)
1087 functiondecl
& curfunc
= *func
->second
;
1088 if (curfunc
.synthetic
)
1090 if (!startswith(curfunc
.name
, "__global_"))
1092 if (!s
.verbose
&& startswith(curfunc
.name
, "__global__"))
1094 curfunc
.printsigtags(cout
, s
.verbose
>0 /* all_tags */ );
1098 // Dump the whole script if requested, or if we stop at 2
1099 else if (s
.dump_mode
== systemtap_session::dump_matched_probes
||
1100 s
.dump_mode
== systemtap_session::dump_matched_probes_vars
||
1101 (rc
== 0 && s
.last_pass
== 2) ||
1102 (rc
!= 0 && s
.verbose
> 2))
1103 printscript(s
, cout
);
1105 times (& tms_after
);
1106 gettimeofday (&tv_after
, NULL
);
1109 int np
= s
.probes
.size();
1110 int nf
= s
.functions
.size();
1111 int ne
= s
.embeds
.size();
1112 int ng
= s
.globals
.size();
1113 clog
<< _("Pass 2: analyzed script: ")
1114 << _NF("%d probe, ", "%d probes, ", np
, np
)
1115 << _NF("%d function, ", "%d functions, ", nf
, nf
)
1116 << _NF("%d embed, ", "%d embeds, ", ne
, ne
)
1117 << _NF("%d global ", "%d globals ", ng
, ng
)
1123 missing_rpm_list_print(s
, "-debuginfo");
1125 // Check for unused command line parameters. But - if the argv
1126 // tapset was selected for inclusion, then the user-script need not
1127 // use $* directly, so we want to suppress the warning in this case.
1128 // This is hacky, but we don't have a formal way of tracking tokens
1129 // that came from command line arguments so as to do set-subtraction
1132 bool argc_found
=false, argv_found
=false;
1133 for (unsigned i
= 0; i
<s
.globals
.size(); i
++) {
1134 if (s
.globals
[i
]->unmangled_name
== "argc") argc_found
= true;
1135 if (s
.globals
[i
]->unmangled_name
== "argv") argv_found
= true;
1137 if (!argc_found
&& !argv_found
)
1138 for (unsigned i
= 0; i
<s
.used_args
.size(); i
++)
1139 if (! s
.used_args
[i
])
1140 s
.print_warning (_F("unused command line option $%u/@%u", i
+1, i
+1));
1142 if (rc
&& !s
.dump_mode
&& !s
.try_server ())
1143 cerr
<< _("Pass 2: analysis failed. [man error::pass2]") << endl
;
1145 PROBE1(stap
, pass2__end
, &s
);
1147 assert_no_interrupts();
1148 // NB: none of the dump modes need to go beyond pass-2. If this changes, break
1149 // into individual modes here.
1150 if (rc
|| s
.last_pass
== 2 || s
.dump_mode
)
1153 rc
= prepare_translate_pass (s
);
1154 assert_no_interrupts();
1157 // Generate hash. There isn't any point in generating the hash
1158 // if last_pass is 2, since we'll quit before using it.
1159 if (s
.use_script_cache
)
1162 unsigned saved_verbose
;
1165 // Make sure we're in verbose mode, so that printscript()
1166 // will output function/probe bodies.
1167 saved_verbose
= s
.verbose
;
1169 printscript(s
, o
); // Print script to 'o'
1170 s
.verbose
= saved_verbose
;
1174 find_script_hash (s
, o
.str());
1176 // See if we can use cached source/module.
1177 if (get_script_from_cache(s
))
1179 // We may still need to build uprobes, if it's not also cached.
1181 rc
= uprobes_pass(s
);
1184 if (s
.module_sign_given
)
1186 // when run on client as --sign-module, mok fingerprints are result of mokutil -l
1187 // when run from server as --sign-module=PATH, mok fingerprint is given by PATH
1189 if (!s
.module_sign_mok_path
.empty())
1191 string mok_fingerprint
;
1192 split_path (s
.module_sign_mok_path
, mok_path
, mok_fingerprint
);
1193 s
.mok_fingerprints
.clear();
1194 s
.mok_fingerprints
.push_back(mok_fingerprint
);
1197 clog
<< _F("Signing %s with mok key %s", s
.module_filename().c_str(), mok_path
.c_str())
1199 rc
= sign_module (s
.tmpdir
, s
.module_filename(), s
.mok_fingerprints
, mok_path
, s
.kernel_build_tree
);
1203 // If our last pass isn't 5, we're done (since passes 3 and
1204 // 4 just generate what we just pulled out of the cache).
1205 assert_no_interrupts();
1206 if (rc
|| s
.last_pass
< 5) return rc
;
1208 // Short-circuit to pass 5.
1213 // PASS 3: TRANSLATION
1214 // (BPF does translation and compilation at once in pass 4.)
1215 s
.verbose
= s
.perpass_verbose
[2];
1216 times (& tms_before
);
1217 gettimeofday (&tv_before
, NULL
);
1218 PROBE1(stap
, pass3__start
, &s
);
1220 if (s
.runtime_mode
== systemtap_session::bpf_runtime
)
1222 times (& tms_after
);
1223 gettimeofday (&tv_after
, NULL
);
1224 PROBE1(stap
, pass3__end
, &s
);
1227 clog
<< _("Pass 3: pass skipped for stapbpf runtime ")
1231 assert_no_interrupts();
1232 if (s
.last_pass
== 3)
1237 rc
= translate_pass (s
);
1239 if (! rc
&& s
.last_pass
== 3)
1241 ifstream
i (s
.translated_source
.c_str());
1245 times (& tms_after
);
1246 gettimeofday (&tv_after
, NULL
);
1249 clog
<< _("Pass 3: translated to C into \"")
1250 << s
.translated_source
1256 if (rc
&& ! s
.try_server ())
1257 cerr
<< _("Pass 3: translation failed. [man error::pass3]") << endl
;
1259 PROBE1(stap
, pass3__end
, &s
);
1261 assert_no_interrupts();
1262 if (rc
|| s
.last_pass
== 3)
1266 // PASS 4: COMPILATION
1267 s
.verbose
= s
.perpass_verbose
[3];
1268 times (& tms_before
);
1269 gettimeofday (&tv_before
, NULL
);
1270 PROBE1(stap
, pass4__start
, &s
);
1272 if (s
.runtime_mode
== systemtap_session::bpf_runtime
)
1273 rc
= translate_bpf_pass (s
);
1278 find_stapconf_hash(s
);
1279 get_stapconf_from_cache(s
);
1281 rc
= compile_pass (s
);
1284 if (! rc
&& s
.last_pass
<= 4)
1286 cout
<< ((s
.hash_path
== "") ? s
.module_filename() : s
.hash_path
);
1290 times (& tms_after
);
1291 gettimeofday (&tv_after
, NULL
);
1295 if (s
.runtime_mode
== systemtap_session::bpf_runtime
)
1296 clog
<< _("Pass 4: compiled BPF into \"");
1298 clog
<< _("Pass 4: compiled C into \"");
1299 clog
<< s
.module_filename() << "\" " << TIMESPRINT
<< endl
;
1302 if (rc
&& ! s
.try_server ())
1304 cerr
<< _("Pass 4: compilation failed. [man error::pass4]") << endl
;
1305 if (s
.runtime_mode
== systemtap_session::kernel_runtime
)
1307 // PR30858: report kernel version support
1308 auto x
= s
.kernel_version_range();
1309 bool outside
= (strverscmp (x
.first
.c_str(), s
.kernel_base_release
.c_str()) > 0 ||
1310 strverscmp (x
.second
.c_str(), s
.kernel_base_release
.c_str()) < 0);
1311 cerr
<< _F("Kernel version %s is %s tested range %s ... %s\n",
1312 s
.kernel_base_release
.c_str(),
1313 outside
? "outside" : "within",
1314 x
.first
.c_str(), x
.second
.c_str());
1319 // Update cache. Cache cleaning is kicked off at the
1320 // beginning of this function.
1321 if (s
.use_script_cache
)
1322 add_script_to_cache(s
);
1323 if (s
.use_cache
&& !s
.runtime_usermode_p())
1324 add_stapconf_to_cache(s
);
1326 // We may need to save the module in $CWD if the cache was
1327 // inaccessible for some reason.
1328 if (! s
.use_script_cache
&& s
.last_pass
<= 4)
1329 s
.save_module
= true;
1333 if (!rc
&& s
.module_sign_given
)
1335 // when run on client as --sign-module, mok fingerprints are result of mokutil -l
1336 // when run from server as --sign-module=PATH, mok fingerprint is given by PATH
1338 if (!s
.module_sign_mok_path
.empty())
1340 string mok_fingerprint
;
1341 split_path (s
.module_sign_mok_path
, mok_path
, mok_fingerprint
);
1342 s
.mok_fingerprints
.clear();
1343 s
.mok_fingerprints
.push_back(mok_fingerprint
);
1347 clog
<< _F("Signing %s with mok key %s", s
.module_filename().c_str(), mok_path
.c_str())
1349 rc
= sign_module (s
.tmpdir
, s
.module_filename(), s
.mok_fingerprints
, mok_path
, s
.kernel_build_tree
);
1353 // Copy module to the current directory.
1354 if (!rc
&& s
.save_module
&& !pending_interrupts
)
1356 string module_src_path
= s
.tmpdir
+ "/" + s
.module_filename();
1357 string module_dest_path
= s
.module_filename();
1358 copy_file(module_src_path
, module_dest_path
, s
.verbose
> 1);
1361 // Copy uprobes module to the current directory.
1362 if (s
.save_uprobes
&& !s
.uprobes_path
.empty() && !pending_interrupts
)
1364 rc
= create_dir("uprobes");
1366 copy_file(s
.uprobes_path
, "uprobes/uprobes.ko", s
.verbose
> 1);
1370 PROBE1(stap
, pass4__end
, &s
);
1375 // Unprivileged (PR30321) part of pass 5
1377 pass_5_1 (systemtap_session
&s
, vector
<remote
*> targets
)
1379 // PASS 5: RUN (part 1 - unprivileged)
1380 s
.verbose
= s
.perpass_verbose
[4];
1382 // Prepare the staprun cmdline, but don't spawn it.
1383 // Store staprun cmdline in s->tmpdir + "/staprun_args".
1384 // Run under unprivileged user.
1385 rc
= remote::run1(targets
);
1389 // Privileged (PR30321) part of pass 5
1391 pass_5_2 (systemtap_session
&s
, vector
<remote
*> targets
)
1393 // PASS 5: RUN (part 2 - privileged)
1394 s
.verbose
= s
.perpass_verbose
[4];
1395 struct tms tms_before
;
1396 times (& tms_before
);
1397 struct timeval tv_before
;
1398 gettimeofday (&tv_before
, NULL
);
1399 // NB: this message is a judgement call. The other passes don't emit
1400 // a "hello, I'm starting" message, but then the others aren't interactive
1401 // and don't take an indefinite amount of time.
1402 PROBE1(stap
, pass5__start
, &s
);
1403 if (s
.verbose
) clog
<< _("Pass 5: starting run.") << endl
;
1404 // Spawn staprun with already prepared commandline.
1405 // Retreive staprun cmdline in s->tmpdir + "/staprun_args".
1406 // Run under privileged user.
1407 int rc
= remote::run2(targets
);
1408 struct tms tms_after
;
1409 times (& tms_after
);
1410 unsigned _sc_clk_tck
= sysconf (_SC_CLK_TCK
);
1411 struct timeval tv_after
;
1412 gettimeofday (&tv_after
, NULL
);
1413 if (s
.verbose
) clog
<< _("Pass 5: run completed ")
1418 cerr
<< _("Pass 5: run failed. [man error::pass5]") << endl
;
1420 // Interrupting pass-5 to quit is normal, so we want an EXIT_SUCCESS below.
1421 pending_interrupts
= 0;
1423 PROBE1(stap
, pass5__end
, &s
);
1429 cleanup (systemtap_session
&s
, int rc
)
1431 // PASS 6: cleaning up
1432 PROBE1(stap
, pass6__start
, &s
);
1434 for (systemtap_session::session_map_t::iterator it
= s
.subsessions
.begin();
1435 it
!= s
.subsessions
.end(); ++it
)
1436 cleanup (*it
->second
, rc
);
1438 // update the database information
1439 if (!rc
&& s
.tapset_compile_coverage
&& !pending_interrupts
) {
1440 #ifdef HAVE_LIBSQLITE3
1441 update_coverage_db(s
);
1443 cerr
<< _("Coverage database not available without libsqlite3") << endl
;
1447 s
.report_suppression();
1449 PROBE1(stap
, pass6__end
, &s
);
1453 passes_0_4_again_with_server (systemtap_session
&s
)
1455 // Not a server and not already using a server.
1456 assert (! s
.client_options
);
1457 assert (s
.specified_servers
.empty ());
1459 // Specify default server(s).
1460 s
.specified_servers
.push_back ("");
1462 // Reset the previous temporary directory and start fresh
1465 // Try to compile again, using the server
1466 clog
<< _("Attempting compilation using a compile server")
1469 int rc
= passes_0_4 (s
);
1474 passes_1_5 (systemtap_session
&s
, vector
<remote
*> targets
)
1478 // Discover and loop over each unique session created by the remote targets.
1479 set
<systemtap_session
*> sessions
;
1480 for (unsigned i
= 0; i
< targets
.size(); ++i
)
1481 sessions
.insert(targets
[i
]->get_session());
1483 for (set
<systemtap_session
*>::iterator it
= sessions
.begin();
1484 rc
== 0 && !pending_interrupts
&& it
!= sessions
.end(); ++it
)
1486 systemtap_session
& ss
= **it
;
1488 clog
<< _F("Session arch: %s release: %s",
1489 ss
.architecture
.c_str(), ss
.kernel_release
.c_str())
1491 << _F("Build tree: \"%s\"",
1492 ss
.kernel_build_tree
.c_str())
1496 // If requested, query server status. This is independent
1498 nss_client_query_server_status (ss
);
1500 // If requested, manage trust of servers. This is
1501 // independent of other tasks.
1502 nss_client_manage_server_trust (ss
);
1505 // Run the passes only if a script has been specified or
1506 // if we're dumping something. The requirement for a
1507 // script has already been checked in
1508 // systemtap_session::check_options.
1509 if (ss
.have_script
|| ss
.dump_mode
)
1511 // Run passes 0-4 for each unique session, either
1512 // locally or using a compile-server.
1513 ss
.init_try_server ();
1514 if ((rc
= passes_0_4 (ss
)))
1516 // Compilation failed.
1517 // Try again using a server if appropriate.
1518 if (ss
.try_server ())
1519 rc
= passes_0_4_again_with_server (ss
);
1521 if (rc
|| s
.perpass_verbose
[0] >= 1)
1522 s
.explain_auto_options ();
1526 if (rc
== 0 && s
.have_script
&& s
.last_pass
>= 5 && ! pending_interrupts
)
1528 rc
= pass_5_1 (s
, targets
);
1529 rc
= pass_5_2 (s
, targets
);
1537 passes_1_5_build_as (systemtap_session
&s
, vector
<remote
*> targets
)
1540 // logging verbosity treshold
1541 unsigned int vt
= 2;
1543 // Discover and loop over each unique session created by the remote targets.
1544 set
<systemtap_session
*> sessions
;
1545 for (unsigned i
= 0; i
< targets
.size(); ++i
)
1546 sessions
.insert(targets
[i
]->get_session());
1548 // PR30321: Privilege separation
1549 // Fork the stap process in two: An unprivileged child, and a privileged parent
1550 // Child will run passes 1-4 and part of pass 5 (up to preparing staprun cmdline
1551 // Parent will wait, spawn staprun (second part of pass 5), and finish.
1552 pid_t frkrc
= fork();
1555 clog
<< _("ERROR: Fork failed. Terminating...") << endl
;
1556 return EXIT_FAILURE
;
1558 else if (frkrc
== 0)
1561 if (s
.build_as
!= "")
1563 // Start running under an unprivileged user
1564 rc
= run_unprivileged(s
.build_as
, s
.build_as_uid
, s
.build_as_gid
, s
.verbose
);
1565 if (rc
!= EXIT_SUCCESS
)
1568 if (s
.verbose
>= vt
)
1569 clog
<< _F("Child pid=%d, uid=%d, euid=%d, gid=%d, egid=%d\n",
1570 getpid(), getuid(), geteuid(), getgid(), getegid());
1573 for (set
<systemtap_session
*>::iterator it
= sessions
.begin();
1574 rc
== 0 && !pending_interrupts
&& it
!= sessions
.end(); ++it
)
1576 systemtap_session
& ss
= **it
;
1578 clog
<< _F("Session arch: %s release: %s",
1579 ss
.architecture
.c_str(), ss
.kernel_release
.c_str())
1581 << _F("Build tree: \"%s\"", ss
.kernel_build_tree
.c_str())
1585 // If requested, query server status. This is independent
1587 nss_client_query_server_status (ss
);
1589 // If requested, manage trust of servers. This is
1590 // independent of other tasks.
1591 nss_client_manage_server_trust (ss
);
1594 // Run the passes only if a script has been specified or
1595 // if we're dumping something. The requirement for a
1596 // script has already been checked in
1597 // systemtap_session::check_options.
1598 if (ss
.have_script
|| ss
.dump_mode
)
1600 // Run passes 0-4 for each unique session, either
1601 // locally or using a compile-server.
1602 ss
.init_try_server ();
1603 if ((rc
= passes_0_4 (ss
)))
1605 // Compilation failed.
1606 // Try again using a server if appropriate.
1607 if (ss
.try_server ())
1608 rc
= passes_0_4_again_with_server (ss
);
1610 if (rc
|| s
.perpass_verbose
[0] >= 1)
1611 s
.explain_auto_options ();
1615 // Run pass 5, if requested (part 1/2 (unprivileged))
1616 if (rc
== 0 && s
.have_script
&& s
.last_pass
>= 5 && ! pending_interrupts
)
1617 rc
= pass_5_1 (s
, targets
);
1618 if (s
.verbose
>= vt
)
1619 clog
<< _F("Child finished running, tmpdir is %s", s
.tmpdir
.c_str())
1626 if (s
.verbose
>= vt
)
1627 clog
<< _F("Parent pid=%d, uid=%d, euid=%d, gid=%d, egid=%d\n",
1628 getpid(), getuid(), geteuid(), getgid(), getegid());
1630 (void)waitpid(frkrc
, &wstatus
, 0);
1631 rc
= WEXITSTATUS(wstatus
);
1634 // Run pass 5, if requested (part 2/2 (privileged))
1635 if (s
.verbose
>= vt
)
1636 clog
<< _F("Parent about to execute staprun, tmpdir is %s", s
.tmpdir
.c_str())
1638 if (rc
== 0 && s
.have_script
&& s
.last_pass
>= 5 && ! pending_interrupts
)
1639 rc
= pass_5_2 (s
, targets
);
1644 main (int argc
, char * const argv
[])
1646 // Initialize defaults.
1648 systemtap_session s
;
1650 setlocale (LC_ALL
, "");
1651 bindtextdomain (PACKAGE
, LOCALEDIR
);
1652 textdomain (PACKAGE
);
1655 // Set up our handler to catch routine signals, to allow clean
1656 // and reasonably timely exit.
1657 setup_signals(&handle_interrupt
);
1659 // PR13520: Parse $SYSTEMTAP_DIR/rc for extra options
1660 string rc_file
= s
.data_path
+ "/rc";
1661 ifstream
rcf (rc_file
.c_str());
1664 memset (& words
, 0, sizeof(words
));
1667 while (getline (rcf
, rcline
))
1669 rc
= wordexp (rcline
.c_str(), & words
, WRDE_NOCMD
|WRDE_UNDEF
|
1670 (linecount
> 0 ? WRDE_APPEND
: 0));
1671 // NB: WRDE_APPEND automagically reallocates words.* as more options are added.
1677 int extended_argc
= words
.we_wordc
+ argc
;
1678 char **extended_argv
= (char**) calloc (extended_argc
+ 1, sizeof(char*));
1679 if (rc
|| !extended_argv
)
1681 clog
<< _F("Error processing extra options in %s", rc_file
.c_str());
1682 return EXIT_FAILURE
;
1684 // Copy over the arguments *by reference*, first the ones from the rc file.
1685 char **p
= & extended_argv
[0];
1687 for (unsigned i
=0; i
<words
.we_wordc
; i
++) *p
++ = words
.we_wordv
[i
];
1688 for (int j
=1; j
<argc
; j
++) *p
++ = argv
[j
];
1691 // Process the command line.
1692 rc
= s
.parse_cmdline (extended_argc
, extended_argv
);
1696 #if HAVE_LANGUAGE_SERVER_SUPPORT
1697 if(s
.language_server_mode
){
1698 // The language server commuinicates with the client via stdio, so the systemtap verbosity should be 0
1699 // It's best to keep the verbosity within the lang-server since it prevents accidental cout usage which
1700 // will cause faliures (Ex. s.version() uses cout)
1701 // Instead the LS verbosity should be set
1702 s
.lang_server
= new language_server(&s
, s
.verbose
);
1704 for(int i
= 0; i
< 5; i
++)
1705 s
.perpass_verbose
[i
] = 0;
1709 // Create the temp dir.
1712 if (words
.we_wordc
> 0 && s
.verbose
> 1)
1713 clog
<< _F("Extra options in %s: %d\n", rc_file
.c_str(), (int)words
.we_wordc
);
1715 // Check for options conflicts. Exits if errors are detected.
1716 s
.check_options (extended_argc
, extended_argv
);
1718 // We don't need these strings any more.
1720 free (extended_argv
);
1722 // arguments parsed; get down to business
1726 // Need to send the verbose message here, rather than in the session ctor, since
1727 // we didn't know if verbose was set.
1728 if (rc
== 0 && s
.verbose
>1)
1729 clog
<< _F("Created temporary directory \"%s\"", s
.tmpdir
.c_str()) << endl
;
1731 // Run the benchmark and quit right away.
1732 if (s
.benchmark_sdt_loops
|| s
.benchmark_sdt_threads
)
1733 return run_sdt_benchmark(s
);
1735 // Prepare connections for each specified remote target.
1736 vector
<remote
*> targets
;
1737 bool fake_remote
=false;
1738 if (s
.remote_uris
.empty())
1741 s
.remote_uris
.push_back("direct:");
1743 for (unsigned i
= 0; rc
== 0 && i
< s
.remote_uris
.size(); ++i
)
1745 // PR13354: pass remote id#/url only in non --remote=HOST cases
1746 remote
*target
= remote::create(s
, s
.remote_uris
[i
],
1747 fake_remote
? -1 : (int)i
);
1749 targets
.push_back(target
);
1755 #if HAVE_LANGUAGE_SERVER_SUPPORT
1756 if(s
.language_server_mode
){
1757 int r
= s
.lang_server
->run();
1758 delete s
.lang_server
;
1763 // FIXME: For now, only attempt local interactive use.
1764 if (s
.interactive_mode
&& fake_remote
)
1766 #ifdef HAVE_LIBREADLINE
1767 rc
= interactive_mode (s
, targets
);
1772 if (s
.build_as
!= "")
1773 rc
= passes_1_5_build_as(s
, targets
);
1775 rc
= passes_1_5(s
, targets
);
1779 for (unsigned i
= 0; i
< targets
.size(); ++i
)
1783 assert_no_interrupts();
1784 return (rc
) ? EXIT_FAILURE
: EXIT_SUCCESS
;
1786 catch (const interrupt_exception
& e
) {
1787 // User entered ctrl-c, exit quietly.
1788 return EXIT_FAILURE
;
1790 catch (const exit_exception
& e
) {
1791 // Exiting for any quiet reason.
1794 catch (const bad_alloc
&e
) {
1795 cerr
<< "Out of memory. Please check --rlimit-as and memory availability." << endl
;
1796 cerr
<< e
.what() << endl
;
1797 return EXIT_FAILURE
;
1799 catch (const exception
&e
) {
1800 // Some other uncaught exception.
1801 cerr
<< e
.what() << endl
;
1802 return EXIT_FAILURE
;
1805 // Catch all other unknown exceptions.
1806 cerr
<< _("ERROR: caught unknown exception!") << endl
;
1807 return EXIT_FAILURE
;
1811 /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */