]> sourceware.org Git - systemtap.git/blob - main.cxx
Update tty.stp tapset for Linux 6.1 and newer
[systemtap.git] / main.cxx
1 // systemtap translator/driver
2 // Copyright (C) 2005-2019 Red Hat Inc.
3 // Copyright (C) 2005 IBM Corp.
4 // Copyright (C) 2006 Intel Corporation.
5 //
6 // This file is part of systemtap, and is free software. You can
7 // redistribute it and/or modify it under the terms of the GNU General
8 // Public License (GPL); either version 2, or (at your option) any
9 // later version.
10
11 #include "config.h"
12 #include "staptree.h"
13 #include "parse.h"
14 #include "elaborate.h"
15 #include "translate.h"
16 #include "buildrun.h"
17 #include "session.h"
18 #include "hash.h"
19 #include "cache.h"
20 #include "util.h"
21 #include "coveragedb.h"
22 #include "rpm_finder.h"
23 #include "task_finder.h"
24 #include "cscommon.h"
25 #include "csclient.h"
26 #include "client-nss.h"
27 #include "remote.h"
28 #include "tapsets.h"
29 #include "setupdwfl.h"
30 #ifdef HAVE_LIBREADLINE
31 #include "interactive.h"
32 #endif
33 #if HAVE_LANGUAGE_SERVER_SUPPORT
34 #include "language-server/stap-language-server.h"
35 #endif
36
37 #include "bpf.h"
38
39 #if ENABLE_NLS
40 #include <libintl.h>
41 #include <locale.h>
42 #endif
43
44 #include "stap-probe.h"
45
46 #include <cstdlib>
47 #include <thread>
48 #include <algorithm>
49
50 extern "C" {
51 #include <glob.h>
52 #include <unistd.h>
53 #include <signal.h>
54 #include <sys/utsname.h>
55 #include <sys/times.h>
56 #include <sys/time.h>
57 #include <sys/stat.h>
58 #include <time.h>
59 #include <unistd.h>
60 #include <wordexp.h>
61 #include <ftw.h>
62 #include <fcntl.h>
63 #include <sys/wait.h>
64 }
65
66 using namespace std;
67
68 static void
69 uniq_list(list<string>& l)
70 {
71 set<string> s;
72 list<string>::iterator i = l.begin();
73 while (i != l.end())
74 if (s.insert(*i).second)
75 ++i;
76 else
77 i = l.erase(i);
78 }
79
80 static void
81 printscript(systemtap_session& s, ostream& o)
82 {
83 if (s.dump_mode == systemtap_session::dump_matched_probes ||
84 s.dump_mode == systemtap_session::dump_matched_probes_vars)
85 {
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;
89
90 // Pre-process the probe alias
91 for (unsigned i=0; i<s.probes.size(); i++)
92 {
93 assert_no_interrupts();
94
95 derived_probe* p = s.probes[i];
96 vector<probe*> chain;
97 p->collect_derivation_chain (chain);
98
99 if (s.verbose > 2) {
100 p->printsig(cerr); cerr << endl;
101 cerr << "chain[" << chain.size() << "]:" << endl;
102 for (unsigned j=0; j<chain.size(); j++)
103 {
104 cerr << " [" << j << "]: " << endl;
105 cerr << "\tlocations[" << chain[j]->locations.size() << "]:" << endl;
106 for (unsigned k=0; k<chain[j]->locations.size(); k++)
107 {
108 cerr << "\t [" << k << "]: ";
109 chain[j]->locations[k]->print(cerr);
110 cerr << endl;
111 }
112 const probe_alias *a = chain[j]->get_alias();
113 if (a)
114 {
115 cerr << "\taliases[" << a->alias_names.size() << "]:" << endl;
116 for (unsigned k=0; k<a->alias_names.size(); k++)
117 {
118 cerr << "\t [" << k << "]: ";
119 a->alias_names[k]->print(cerr);
120 cerr << endl;
121 }
122 }
123 }
124 }
125
126 const string& pp = lex_cast(*p->script_location());
127
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))
133 continue;
134
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);
139 }
140
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)
143 {
144 std::string pp;
145
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");
149 else
150 pp = it->first;
151
152 // Print the locals and arguments for -L mode only
153 if (s.dump_mode == systemtap_session::dump_matched_probes_vars)
154 {
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)
161 {
162 derived_probe* p = *ix;
163 // collect available locals of the probe
164 for (unsigned j=0; j<p->locals.size(); j++)
165 {
166 stringstream tmps;
167 vardecl* v = p->locals[j];
168 v->printsig (tmps);
169 var_count[tmps.str()]++;
170 var_list.push_back(tmps.str());
171 }
172 // collect arguments of the probe if there
173 list<string> arg_set;
174 p->getargs(arg_set);
175 for (list<string>::iterator ia=arg_set.begin(); ia!=arg_set.end(); ++ia) {
176 arg_count[*ia]++;
177 arg_list.push_back(*ia);
178 }
179
180 // If verbosity is set, we want to print out all instances of duplicated probes and
181 // distinguish them with the PC address.
182 if (s.verbose > 0)
183 {
184 // We want to print the probe point signature (without the nested components).
185 std::ostringstream sig;
186 p->printsig_nonest(sig);
187 if (s.verbose > 1)
188 p->printsig_nested(sig);
189
190 if (s.dump_mode == systemtap_session::dump_matched_probes_vars && isatty(STDOUT_FILENO))
191 o << s.colorize(sig.str(), "source");
192 else
193 o << sig.str();
194
195 for (list<string>::iterator ir=var_list.begin(); ir!=var_list.end(); ++ir)
196 o << " " << *ir;
197 for (list<string>::iterator ir=arg_list.begin(); ir!=arg_list.end(); ++ir)
198 o << " " << *ir;
199
200 o << endl;
201
202 arg_list.clear();
203 var_list.clear();
204 }
205 }
206
207 if (!(s.verbose > 0))
208 {
209 uniq_list(arg_list);
210 uniq_list(var_list);
211
212 o << pp;
213
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
217 o << " " << *ir;
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
220 o << " " << *ir;
221
222 o << endl;
223 }
224 }
225 else
226 {
227 o << pp;
228 o << endl;
229 }
230 }
231 }
232 else
233 {
234 if (s.embeds.size() > 0)
235 o << _("# global embedded code") << endl;
236 for (unsigned i=0; i<s.embeds.size(); i++)
237 {
238 assert_no_interrupts();
239 embeddedcode* ec = s.embeds[i];
240 ec->print (o);
241 o << endl;
242 }
243
244 if (s.globals.size() > 0)
245 o << _("# globals") << endl;
246 for (unsigned i=0; i<s.globals.size(); i++)
247 {
248 assert_no_interrupts();
249 vardecl* v = s.globals[i];
250 v->printsig (o);
251 if (s.verbose && v->init)
252 {
253 o << " = ";
254 v->init->print(o);
255 }
256 o << endl;
257 }
258
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++)
262 {
263 assert_no_interrupts();
264 functiondecl* f = it->second;
265 f->printsig (o);
266 o << endl;
267 if (f->locals.size() > 0)
268 o << _(" # locals") << endl;
269 for (unsigned j=0; j<f->locals.size(); j++)
270 {
271 vardecl* v = f->locals[j];
272 o << " ";
273 v->printsig (o);
274 o << endl;
275 }
276 if (s.verbose)
277 {
278 o << "{ ";
279 f->body->print (o);
280 o << " }" << endl;
281 }
282 }
283
284 if (s.probes.size() > 0)
285 o << _("# probes") << endl;
286 for (unsigned i=0; i<s.probes.size(); i++)
287 {
288 assert_no_interrupts();
289 derived_probe* p = s.probes[i];
290 p->printsig (o);
291 o << endl;
292 if (p->locals.size() > 0)
293 o << _(" # locals") << endl;
294 for (unsigned j=0; j<p->locals.size(); j++)
295 {
296 vardecl* v = p->locals[j];
297 o << " ";
298 v->printsig (o);
299 o << endl;
300 }
301 if (s.verbose)
302 {
303 o << "{ ";
304 p->body->print (o);
305 o << " }" << endl;
306 }
307 }
308 }
309 }
310
311
312 int pending_interrupts;
313
314 extern "C"
315 void handle_interrupt (int)
316 {
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);
320
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?
326 {
327 char msg[] = "Too many interrupts received, exiting.\n";
328 int fd = 2;
329
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);
335 if (flags == -1)
336 _exit (1);
337
338 if (!(flags & O_NONBLOCK))
339 {
340 if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == 0) {
341 int rc = write (fd, msg, sizeof(msg)-1);
342 if (rc)
343 {
344 /* Do nothing; we don't care if our last gasp went out. */
345 ;
346 }
347 }
348 } /* if ! O_NONBLOCK */
349
350 /* to avoid leaving any side-effects on the stderr device */
351 (void) fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
352 _exit (1);
353 }
354 }
355
356
357 void
358 setup_signals (sighandler_t handler)
359 {
360 struct sigaction sa;
361
362 memset(&sa, 0, sizeof(sa));
363 sa.sa_handler = handler;
364 sigemptyset (&sa.sa_mask);
365 if (handler != SIG_IGN)
366 {
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);
373 }
374 sa.sa_flags = SA_RESTART;
375
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);
382 }
383
384
385 static void
386 sdt_benchmark_thread(unsigned long i, double fp1, float fp2)
387 {
388 PROBE(stap, benchmark__thread__start);
389 fp1 += 0.0;
390 fp2 += 0.0;
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;
407 fp_local1 += 0.0;
408 fp_local2 += 0.0;
409 fp_local3 += 0.0;
410 fp_local4 += 0.0;
411 fp_local5 += 0.0;
412 fp_local6 += 0.0;
413 fp_local7 += 0.0;
414 fp_local8 += 0.0;
415 fp_local9 += 0.0;
416 fp_local10 += 0.0;
417 fp_local11 += 0.0;
418 fp_local12 += 0.0;
419 fp_local13 += 0.0;
420 fp_local14 += 0.0;
421 fp_local15 += 0.0;
422 while (i--)
423 PROBE1(stap, benchmark, i);
424 PROBE(stap, benchmark__thread__end);
425 }
426
427
428 static int
429 run_sdt_benchmark(systemtap_session& s)
430 {
431 unsigned long loops = s.benchmark_sdt_loops ?: 10000000;
432 unsigned long threads = s.benchmark_sdt_threads ?: 1;
433
434 if (s.verbose > 0)
435 clog << _F("Beginning SDT benchmark with %lu loops in %lu threads.",
436 loops, threads) << endl;
437
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);
443
444 PROBE(stap, benchmark__start);
445 {
446 vector<thread> handles;
447 double f = 2.71828;
448 float f2 = 1.41421;
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)
452 handles[i].join();
453 }
454 PROBE(stap, benchmark__end);
455
456 times (& tms_after);
457 gettimeofday (&tv_after, NULL);
458 if (s.verbose > 0)
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))
464 << endl;
465
466 return EXIT_SUCCESS;
467 }
468
469 static set<string> files;
470 static string path_dir;
471
472 static int collect_stp(const char* fpath, const struct stat*,
473 int typeflag, struct FTW* ftwbuf)
474 {
475 if (typeflag == FTW_F)
476 {
477 const char* ext = strrchr(fpath, '.');
478 if (ext && (strcmp(".stp", ext) == 0))
479 files.insert(fpath);
480 }
481 else if (typeflag == FTW_D && ftwbuf->level > 0)
482 {
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;
487 }
488 return FTW_CONTINUE;
489 }
490
491 static int collect_stpm(const char* fpath, const struct stat*,
492 int typeflag, struct FTW* ftwbuf)
493 {
494 if (typeflag == FTW_F)
495 {
496 const char* ext = strrchr(fpath, '.');
497 if (ext && (strcmp(".stpm", ext) == 0))
498 files.insert(fpath);
499 }
500 else if (typeflag == FTW_D && ftwbuf->level > 0)
501 {
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;
506 }
507 return FTW_CONTINUE;
508 }
509
510 #if !HAVE_BPF_DECLS
511 int
512 translate_bpf_pass (systemtap_session &)
513 {
514 return 1;
515 }
516 #endif
517
518 // Compilation passes 0 through 4
519 int
520 passes_0_4 (systemtap_session &s)
521 {
522 int rc = 0;
523
524 // If we don't know the release, there's no hope either locally or on a server.
525 if (s.kernel_release.empty())
526 {
527 if (s.kernel_build_tree.empty())
528 cerr << _("ERROR: kernel release isn't specified") << endl;
529 else
530 cerr << _F("ERROR: kernel release isn't found in \"%s\"",
531 s.kernel_build_tree.c_str()) << endl;
532 return 1;
533 }
534
535 // Perform passes 0 through 4 using a compile server?
536 if (! s.specified_servers.empty ())
537 {
538 #if NEED_BASE_CLIENT_CODE
539 compile_server_client client (s);
540 return client.passes_0_4 ();
541 #else
542 s.print_warning(_("Without NSS or HTTP client support, using a compile-server is not supported by this version of systemtap"));
543
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
546 // NSS.
547 assert (! s.try_server ());
548 s.print_warning(_("Ignoring --use-server"));
549 #endif
550 }
551
552 // PASS 0: setting up
553 s.verbose = s.perpass_verbose[0];
554 PROBE1(stap, pass0__start, &s);
555
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
560 // resolution.
561
562 s.kernel_base_release.assign(s.kernel_release, 0, s.kernel_release.find('-'));
563
564 // Update various paths to include the sysroot, if provided.
565 if (!s.sysroot.empty())
566 {
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);
570 }
571
572 // Now that no further changes to s.kernel_build_tree can occur, let's use it.
573 if (!s.runtime_usermode_p())
574 {
575 if ((rc = s.parse_kernel_config ()) != 0
576 || (rc = s.parse_kernel_exports ()) != 0
577 || (rc = s.parse_kernel_functions ()) != 0)
578 {
579 // Try again with a server
580 s.set_try_server ();
581 return rc;
582 }
583 }
584
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";
589
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";
594
595 PROBE1(stap, pass0__end, &s);
596
597 struct tms tms_before;
598 times (& tms_before);
599 struct timeval tv_before;
600 gettimeofday (&tv_before, NULL);
601
602 // PASS 1a: PARSING LIBRARY SCRIPTS
603 PROBE1(stap, pass1a__start, &s);
604
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);
607
608 if (! s.pass_1a_complete)
609 {
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.
613
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;
617
618 if (s.script_file == "-")
619 {
620 user_file_stat_rc = fstat (STDIN_FILENO, & user_file_stat);
621 }
622 else if (s.script_file != "")
623 {
624 if (s.run_example)
625 {
626 files.clear();
627 path_dir = string(PKGDATADIR) + "/examples";
628 (void) nftw(path_dir.c_str(), collect_stp, 1, FTW_ACTIONRETVAL);
629
630 vector<string> examples;
631 for (auto it = files.begin(); it != files.end(); ++it)
632 {
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);
637 }
638
639 if (examples.size() > 1)
640 {
641 cerr << "Multiple examples found: " << endl;
642 for (auto it = examples.begin(); it != examples.end(); ++it)
643 cerr << " " << *it << endl;
644 return 1;
645 }
646 else if (examples.size() == 0)
647 {
648 cerr << _F("Example '%s' was not found under '%s'", s.script_file.c_str(), path_dir.c_str()) << endl;
649 return 1;
650 }
651 else
652 s.script_file = examples[0];
653 }
654
655 user_file_stat_rc = stat (s.script_file.c_str(), & user_file_stat);
656 }
657 // otherwise, rc is 0 for a command line script
658
659 vector<string> version_suffixes;
660 if (!s.runtime_usermode_p())
661 {
662 // Construct kernel-versioning search path
663 string kvr = s.kernel_release;
664
665 // add full kernel-version-release (2.6.NN-FOOBAR)
666 version_suffixes.push_back ("/" + kvr);
667
668 // add kernel version (2.6.NN)
669 if (kvr != s.kernel_base_release)
670 {
671 kvr = s.kernel_base_release;
672 version_suffixes.push_back ("/" + kvr);
673 }
674
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)
679 {
680 kvr.erase(dot2_index);
681 version_suffixes.push_back ("/" + kvr);
682 dot2_index = kvr.rfind ('.');
683 }
684 }
685
686 // add empty string as last element
687 version_suffixes.push_back ("");
688
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);
694
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]);
707
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;
714
715 for (unsigned i=0; i<s.include_path.size(); i++)
716 {
717 // now iterate upon it
718 for (unsigned k=0; k<version_suffixes.size(); k++)
719 {
720 int flags = FTW_ACTIONRETVAL;
721 string dir = s.include_path[i] + version_suffixes[k];
722 files.clear();
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);
726
727 unsigned prev_s_library_files = s.library_files.size();
728
729 for (auto it = files.begin(); it != files.end(); ++it)
730 {
731 assert_no_interrupts();
732
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)
738 {
739 cerr
740 << _F("usage error: macro tapset file '%s' cannot be run directly as a session script.",
741 it->c_str()) << endl;
742 rc ++;
743 }
744
745 // PR11949: duplicate-eliminate tapset files
746 if (stat_rc == 0)
747 {
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())
751 {
752 if (s.verbose>2)
753 clog << _F("Skipping tapset \"%s\", duplicate inode.", it->c_str()) << endl;
754 continue;
755 }
756 seen_library_macro_files.insert (here);
757 }
758
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())
763 {
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())
766 {
767 if (s.verbose>2)
768 clog << _F("Skipping tapset \"%s\", duplicate name.", it->c_str()) << endl;
769 continue;
770 }
771 seen_library_macro_files_names.insert (tail_part);
772 }
773
774 if (s.verbose>2)
775 clog << _F("Processing tapset \"%s\"", it->c_str()) << endl;
776
777 stapfile* f = parse_library_macros (s, *it);
778 if (f == 0)
779 s.print_warning(_F("macro tapset \"%s\" has errors, and will be skipped.", it->c_str()));
780 else
781 s.library_files.push_back (f);
782 }
783
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;
790 }
791 }
792
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;
796
797 for (unsigned i=0; i<s.include_path.size(); i++)
798 {
799 // now iterate upon it
800 for (unsigned k=0; k<version_suffixes.size(); k++)
801 {
802 int flags = FTW_ACTIONRETVAL;
803 string dir = s.include_path[i] + version_suffixes[k];
804 files.clear();
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);
808
809 unsigned prev_s_library_files = s.library_files.size();
810
811 for (auto it = files.begin(); it != files.end(); ++it)
812 {
813 unsigned tapset_flags = pf_guru | pf_squash_errors;
814
815 // The first path is special, as it's the builtin tapset.
816 // Allow all features no matter what s.compatible says.
817 if (i == 0)
818 tapset_flags |= pf_no_compatible;
819
820 if (it->find("/PATH/") != string::npos)
821 tapset_flags |= pf_auto_path;
822
823 assert_no_interrupts();
824
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)
830 {
831 cerr
832 << _F("usage error: tapset file '%s' cannot be run directly as a session script.",
833 it->c_str()) << endl;
834 rc ++;
835 }
836
837 // PR11949: duplicate-eliminate tapset files
838 if (stat_rc == 0)
839 {
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())
843 {
844 if (s.verbose>2)
845 clog << _F("Skipping tapset \"%s\", duplicate inode.", it->c_str()) << endl;
846 continue;
847 }
848 seen_library_files.insert (here);
849 }
850
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())
855 {
856 string tail_part = full_path.substr(tapset_base.size());
857 if (seen_library_files_names.find (tail_part) != seen_library_files_names.end())
858 {
859 if (s.verbose>2)
860 clog << _F("Skipping tapset \"%s\", duplicate name.", it->c_str()) << endl;
861 continue;
862 }
863 seen_library_files_names.insert (tail_part);
864 }
865
866 if (s.verbose>2)
867 clog << _F("Processing tapset \"%s\"", it->c_str()) << endl;
868
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.
876
877 stapfile* f = parse (s, *it, tapset_flags);
878 if (f == 0)
879 s.print_warning(_F("tapset \"%s\" has errors, and will be skipped", it->c_str()));
880 else
881 {
882 assert (f->privileged);
883 s.library_files.push_back (f);
884 }
885 }
886
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;
893 }
894 }
895
896 if (s.num_errors())
897 rc ++;
898
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;
903 }
904
905 // PASS 1b: PARSING USER SCRIPT
906 PROBE1(stap, pass1b__start, &s);
907
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);
911
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
914 // remains NULL.
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)
919 {
920 unsigned user_flags = s.guru_mode ? pf_guru : 0;
921 user_flags |= pf_user_file;
922 if (s.script_file == "-")
923 {
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,
927 user_flags));
928 }
929 else if (s.script_file != "")
930 {
931 s.user_files.push_back (parse (s, s.script_file, user_flags));
932 }
933 else if (s.cmdline_script != "")
934 {
935 istringstream ii (s.cmdline_script);
936 s.user_files.push_back(parse (s, "<input>", ii, user_flags));
937 }
938 else // listing mode
939 {
940 istringstream ii ("probe " + s.dump_matched_pattern + " {}");
941 s.user_files.push_back (parse (s, "<input>", ii, user_flags));
942 }
943
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.
948 unsigned count = 1;
949 for (vector<string>::iterator script = s.additional_scripts.begin(); script != s.additional_scripts.end(); script++)
950 {
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));
954 count ++;
955 }
956
957 for(vector<stapfile*>::iterator it = s.user_files.begin(); it != s.user_files.end(); it++)
958 {
959 if (!(*it))
960 {
961 // Syntax errors already printed.
962 rc ++;
963 }
964 }
965 }
966 else if (s.cmdline_script.empty() &&
967 s.dump_mode == systemtap_session::dump_none) // -e ''
968 {
969 cerr << _("Input file '<input>' is empty.") << endl;
970 rc++;
971 }
972
973 // Dump a list of probe aliases picked up, if requested
974 if (s.dump_mode == systemtap_session::dump_probe_aliases)
975 {
976 set<string> aliases;
977 vector<stapfile*>::const_iterator file;
978 for (file = s.library_files.begin();
979 file != s.library_files.end(); ++file)
980 {
981 vector<probe_alias*>::const_iterator alias;
982 for (alias = (*file)->aliases.begin();
983 alias != (*file)->aliases.end(); ++alias)
984 {
985 stringstream ss;
986 (*alias)->printsig(ss);
987 string str = ss.str();
988 if (!s.verbose && startswith(str, "_"))
989 continue;
990 aliases.insert(str);
991 }
992 }
993
994 set<string>::iterator alias;
995 for (alias = aliases.begin();
996 alias != aliases.end(); ++alias)
997 {
998 cout << *alias << endl;
999 }
1000 }
1001 // Dump the parse tree if this is the last pass
1002 else if (rc == 0 && s.last_pass == 1)
1003 {
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);
1007 cout << endl;
1008 if (s.verbose)
1009 for (unsigned i=0; i<s.library_files.size(); i++)
1010 {
1011 s.library_files[i]->print (cout);
1012 cout << endl;
1013 }
1014 }
1015
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);
1021
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."
1029
1030 // syntax errors, if any, are already printed
1031 if (s.verbose)
1032 {
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)
1037 << getmemusage()
1038 << TIMESPRINT
1039 << endl;
1040 }
1041
1042 if (rc && !s.dump_mode)
1043 cerr << _("Pass 1: parse failed. [man error::pass1]") << endl;
1044
1045 PROBE1(stap, pass1__end, &s);
1046
1047 assert_no_interrupts();
1048 if (rc || s.last_pass == 1 ||
1049 s.dump_mode == systemtap_session::dump_probe_aliases)
1050 return rc;
1051
1052 times (& tms_before);
1053 gettimeofday (&tv_before, NULL);
1054
1055 // PASS 2: ELABORATION
1056 s.verbose = s.perpass_verbose[1];
1057 PROBE1(stap, pass2__start, &s);
1058 rc = semantic_pass (s);
1059
1060 // http handled probes need probe information from pass 2
1061 if (! s.http_servers.empty ())
1062 {
1063 #if NEED_BASE_CLIENT_CODE
1064 compile_server_client client (s);
1065 return client.passes_0_4 ();
1066 #else
1067 s.print_warning(_("Without NSS or HTTP client support, using a compile-server is not supported by this version of systemtap"));
1068
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
1071 // NSS.
1072 assert (! s.try_server ());
1073 s.print_warning(_("Ignoring --use-server"));
1074 #endif
1075 }
1076
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)
1082 {
1083 map<string,functiondecl*>::const_iterator func;
1084 for (func = s.functions.begin();
1085 func != s.functions.end(); ++func)
1086 {
1087 functiondecl& curfunc = *func->second;
1088 if (curfunc.synthetic)
1089 continue;
1090 if (!startswith(curfunc.name, "__global_"))
1091 continue;
1092 if (!s.verbose && startswith(curfunc.name, "__global__"))
1093 continue;
1094 curfunc.printsigtags(cout, s.verbose>0 /* all_tags */ );
1095 cout << endl;
1096 }
1097 }
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);
1104
1105 times (& tms_after);
1106 gettimeofday (&tv_after, NULL);
1107
1108 if (s.verbose) {
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)
1118 << getmemusage()
1119 << TIMESPRINT
1120 << endl;
1121 }
1122
1123 missing_rpm_list_print(s, "-debuginfo");
1124
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
1130 // at this point.
1131 //
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;
1136 }
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));
1141
1142 if (rc && !s.dump_mode && !s.try_server ())
1143 cerr << _("Pass 2: analysis failed. [man error::pass2]") << endl;
1144
1145 PROBE1(stap, pass2__end, &s);
1146
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)
1151 return rc;
1152
1153 rc = prepare_translate_pass (s);
1154 assert_no_interrupts();
1155 if (rc) return rc;
1156
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)
1160 {
1161 ostringstream o;
1162 unsigned saved_verbose;
1163
1164 {
1165 // Make sure we're in verbose mode, so that printscript()
1166 // will output function/probe bodies.
1167 saved_verbose = s.verbose;
1168 s.verbose = 3;
1169 printscript(s, o); // Print script to 'o'
1170 s.verbose = saved_verbose;
1171 }
1172
1173 // Generate hash
1174 find_script_hash (s, o.str());
1175
1176 // See if we can use cached source/module.
1177 if (get_script_from_cache(s))
1178 {
1179 // We may still need to build uprobes, if it's not also cached.
1180 if (s.need_uprobes)
1181 rc = uprobes_pass(s);
1182
1183 #if HAVE_NSS
1184 if (s.module_sign_given)
1185 {
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
1188 string mok_path;
1189 if (!s.module_sign_mok_path.empty())
1190 {
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);
1195 }
1196 if (s.verbose)
1197 clog << _F("Signing %s with mok key %s", s.module_filename().c_str(), mok_path.c_str())
1198 << endl;
1199 rc = sign_module (s.tmpdir, s.module_filename(), s.mok_fingerprints, mok_path, s.kernel_build_tree);
1200 }
1201 #endif
1202
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;
1207
1208 // Short-circuit to pass 5.
1209 return 0;
1210 }
1211 }
1212
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);
1219
1220 if (s.runtime_mode == systemtap_session::bpf_runtime)
1221 {
1222 times (& tms_after);
1223 gettimeofday (&tv_after, NULL);
1224 PROBE1(stap, pass3__end, &s);
1225
1226 if (s.verbose)
1227 clog << _("Pass 3: pass skipped for stapbpf runtime ")
1228 << TIMESPRINT
1229 << endl;
1230
1231 assert_no_interrupts();
1232 if (s.last_pass == 3)
1233 return rc;
1234 }
1235 else
1236 {
1237 rc = translate_pass (s);
1238
1239 if (! rc && s.last_pass == 3)
1240 {
1241 ifstream i (s.translated_source.c_str());
1242 cout << i.rdbuf();
1243 }
1244
1245 times (& tms_after);
1246 gettimeofday (&tv_after, NULL);
1247
1248 if (s.verbose)
1249 clog << _("Pass 3: translated to C into \"")
1250 << s.translated_source
1251 << "\" "
1252 << getmemusage()
1253 << TIMESPRINT
1254 << endl;
1255
1256 if (rc && ! s.try_server ())
1257 cerr << _("Pass 3: translation failed. [man error::pass3]") << endl;
1258
1259 PROBE1(stap, pass3__end, &s);
1260
1261 assert_no_interrupts();
1262 if (rc || s.last_pass == 3)
1263 return rc;
1264 }
1265
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);
1271
1272 if (s.runtime_mode == systemtap_session::bpf_runtime)
1273 rc = translate_bpf_pass (s);
1274 else
1275 {
1276 if (s.use_cache)
1277 {
1278 find_stapconf_hash(s);
1279 get_stapconf_from_cache(s);
1280 }
1281 rc = compile_pass (s);
1282 }
1283
1284 if (! rc && s.last_pass <= 4)
1285 {
1286 cout << ((s.hash_path == "") ? s.module_filename() : s.hash_path);
1287 cout << endl;
1288 }
1289
1290 times (& tms_after);
1291 gettimeofday (&tv_after, NULL);
1292
1293 if (s.verbose)
1294 {
1295 if (s.runtime_mode == systemtap_session::bpf_runtime)
1296 clog << _("Pass 4: compiled BPF into \"");
1297 else
1298 clog << _("Pass 4: compiled C into \"");
1299 clog << s.module_filename() << "\" " << TIMESPRINT << endl;
1300 }
1301
1302 if (rc && ! s.try_server ())
1303 {
1304 cerr << _("Pass 4: compilation failed. [man error::pass4]") << endl;
1305 if (s.runtime_mode == systemtap_session::kernel_runtime)
1306 {
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());
1315 }
1316 }
1317 else
1318 {
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);
1325
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;
1330
1331 #if HAVE_NSS
1332 // PR30749
1333 if (!rc && s.module_sign_given)
1334 {
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
1337 string mok_path;
1338 if (!s.module_sign_mok_path.empty())
1339 {
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);
1344 }
1345
1346 if (s.verbose)
1347 clog << _F("Signing %s with mok key %s", s.module_filename().c_str(), mok_path.c_str())
1348 << endl;
1349 rc = sign_module (s.tmpdir, s.module_filename(), s.mok_fingerprints, mok_path, s.kernel_build_tree);
1350 }
1351 #endif
1352
1353 // Copy module to the current directory.
1354 if (!rc && s.save_module && !pending_interrupts)
1355 {
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);
1359 }
1360
1361 // Copy uprobes module to the current directory.
1362 if (s.save_uprobes && !s.uprobes_path.empty() && !pending_interrupts)
1363 {
1364 rc = create_dir("uprobes");
1365 if (! rc)
1366 copy_file(s.uprobes_path, "uprobes/uprobes.ko", s.verbose > 1);
1367 }
1368 }
1369
1370 PROBE1(stap, pass4__end, &s);
1371
1372 return rc;
1373 }
1374
1375 // Unprivileged (PR30321) part of pass 5
1376 int
1377 pass_5_1 (systemtap_session &s, vector<remote*> targets)
1378 {
1379 // PASS 5: RUN (part 1 - unprivileged)
1380 s.verbose = s.perpass_verbose[4];
1381 int rc;
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);
1386 return rc;
1387 }
1388
1389 // Privileged (PR30321) part of pass 5
1390 int
1391 pass_5_2 (systemtap_session &s, vector<remote*> targets)
1392 {
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 ")
1414 << TIMESPRINT
1415 << endl;
1416
1417 if (rc)
1418 cerr << _("Pass 5: run failed. [man error::pass5]") << endl;
1419 else
1420 // Interrupting pass-5 to quit is normal, so we want an EXIT_SUCCESS below.
1421 pending_interrupts = 0;
1422
1423 PROBE1(stap, pass5__end, &s);
1424
1425 return rc;
1426 }
1427
1428 static void
1429 cleanup (systemtap_session &s, int rc)
1430 {
1431 // PASS 6: cleaning up
1432 PROBE1(stap, pass6__start, &s);
1433
1434 for (systemtap_session::session_map_t::iterator it = s.subsessions.begin();
1435 it != s.subsessions.end(); ++it)
1436 cleanup (*it->second, rc);
1437
1438 // update the database information
1439 if (!rc && s.tapset_compile_coverage && !pending_interrupts) {
1440 #ifdef HAVE_LIBSQLITE3
1441 update_coverage_db(s);
1442 #else
1443 cerr << _("Coverage database not available without libsqlite3") << endl;
1444 #endif
1445 }
1446
1447 s.report_suppression();
1448
1449 PROBE1(stap, pass6__end, &s);
1450 }
1451
1452 static int
1453 passes_0_4_again_with_server (systemtap_session &s)
1454 {
1455 // Not a server and not already using a server.
1456 assert (! s.client_options);
1457 assert (s.specified_servers.empty ());
1458
1459 // Specify default server(s).
1460 s.specified_servers.push_back ("");
1461
1462 // Reset the previous temporary directory and start fresh
1463 s.reset_tmp_dir();
1464
1465 // Try to compile again, using the server
1466 clog << _("Attempting compilation using a compile server")
1467 << endl;
1468
1469 int rc = passes_0_4 (s);
1470 return rc;
1471 }
1472
1473 static int
1474 passes_1_5 (systemtap_session &s, vector<remote*> targets)
1475 {
1476 int rc = 0;
1477
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());
1482
1483 for (set<systemtap_session*>::iterator it = sessions.begin();
1484 rc == 0 && !pending_interrupts && it != sessions.end(); ++it)
1485 {
1486 systemtap_session& ss = **it;
1487 if (ss.verbose > 1)
1488 clog << _F("Session arch: %s release: %s",
1489 ss.architecture.c_str(), ss.kernel_release.c_str())
1490 << endl
1491 << _F("Build tree: \"%s\"",
1492 ss.kernel_build_tree.c_str())
1493 << endl;
1494
1495 #if HAVE_NSS
1496 // If requested, query server status. This is independent
1497 // of other tasks.
1498 nss_client_query_server_status (ss);
1499
1500 // If requested, manage trust of servers. This is
1501 // independent of other tasks.
1502 nss_client_manage_server_trust (ss);
1503 #endif
1504
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)
1510 {
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)))
1515 {
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);
1520 }
1521 if (rc || s.perpass_verbose[0] >= 1)
1522 s.explain_auto_options ();
1523 }
1524 }
1525
1526 if (rc == 0 && s.have_script && s.last_pass >= 5 && ! pending_interrupts)
1527 {
1528 rc = pass_5_1 (s, targets);
1529 rc = pass_5_2 (s, targets);
1530 }
1531 return rc;
1532 }
1533
1534
1535
1536 static int
1537 passes_1_5_build_as (systemtap_session &s, vector<remote*> targets)
1538 {
1539 int rc = 0;
1540 // logging verbosity treshold
1541 unsigned int vt = 2;
1542
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());
1547
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();
1553 if (frkrc == -1)
1554 {
1555 clog << _("ERROR: Fork failed. Terminating...") << endl;
1556 return EXIT_FAILURE;
1557 }
1558 else if (frkrc == 0)
1559 {
1560 // Child process
1561 if (s.build_as != "")
1562 {
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)
1566 return rc;
1567
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());
1571 }
1572
1573 for (set<systemtap_session*>::iterator it = sessions.begin();
1574 rc == 0 && !pending_interrupts && it != sessions.end(); ++it)
1575 {
1576 systemtap_session& ss = **it;
1577 if (ss.verbose > 1)
1578 clog << _F("Session arch: %s release: %s",
1579 ss.architecture.c_str(), ss.kernel_release.c_str())
1580 << endl
1581 << _F("Build tree: \"%s\"", ss.kernel_build_tree.c_str())
1582 << endl;
1583
1584 #if HAVE_NSS
1585 // If requested, query server status. This is independent
1586 // of other tasks.
1587 nss_client_query_server_status (ss);
1588
1589 // If requested, manage trust of servers. This is
1590 // independent of other tasks.
1591 nss_client_manage_server_trust (ss);
1592 #endif
1593
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)
1599 {
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)))
1604 {
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);
1609 }
1610 if (rc || s.perpass_verbose[0] >= 1)
1611 s.explain_auto_options ();
1612 }
1613 }
1614
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())
1620 << endl;
1621 _exit(rc);
1622 }
1623 else
1624 {
1625 // Parent process
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());
1629 int wstatus;
1630 (void)waitpid(frkrc, &wstatus, 0);
1631 rc = WEXITSTATUS(wstatus);
1632 }
1633
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())
1637 << endl;
1638 if (rc == 0 && s.have_script && s.last_pass >= 5 && ! pending_interrupts)
1639 rc = pass_5_2 (s, targets);
1640 return rc;
1641 }
1642
1643 int
1644 main (int argc, char * const argv [])
1645 {
1646 // Initialize defaults.
1647 try {
1648 systemtap_session s;
1649 #if ENABLE_NLS
1650 setlocale (LC_ALL, "");
1651 bindtextdomain (PACKAGE, LOCALEDIR);
1652 textdomain (PACKAGE);
1653 #endif
1654
1655 // Set up our handler to catch routine signals, to allow clean
1656 // and reasonably timely exit.
1657 setup_signals(&handle_interrupt);
1658
1659 // PR13520: Parse $SYSTEMTAP_DIR/rc for extra options
1660 string rc_file = s.data_path + "/rc";
1661 ifstream rcf (rc_file.c_str());
1662 string rcline;
1663 wordexp_t words;
1664 memset (& words, 0, sizeof(words));
1665 int rc = 0;
1666 int linecount = 0;
1667 while (getline (rcf, rcline))
1668 {
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.
1672 linecount ++;
1673 if (rc) break;
1674 }
1675 rcf.close();
1676
1677 int extended_argc = words.we_wordc + argc;
1678 char **extended_argv = (char**) calloc (extended_argc + 1, sizeof(char*));
1679 if (rc || !extended_argv)
1680 {
1681 clog << _F("Error processing extra options in %s", rc_file.c_str());
1682 return EXIT_FAILURE;
1683 }
1684 // Copy over the arguments *by reference*, first the ones from the rc file.
1685 char **p = & extended_argv[0];
1686 *p++ = 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];
1689 *p++ = NULL;
1690
1691 // Process the command line.
1692 rc = s.parse_cmdline (extended_argc, extended_argv);
1693 if (rc != 0)
1694 return rc;
1695
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);
1703 s.verbose = 0;
1704 for(int i = 0; i < 5; i++)
1705 s.perpass_verbose[i] = 0;
1706 }
1707 #endif
1708
1709 // Create the temp dir.
1710 s.create_tmp_dir();
1711
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);
1714
1715 // Check for options conflicts. Exits if errors are detected.
1716 s.check_options (extended_argc, extended_argv);
1717
1718 // We don't need these strings any more.
1719 wordfree (& words);
1720 free (extended_argv);
1721
1722 // arguments parsed; get down to business
1723 if (s.verbose > 1)
1724 s.version ();
1725
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;
1730
1731 // Run the benchmark and quit right away.
1732 if (s.benchmark_sdt_loops || s.benchmark_sdt_threads)
1733 return run_sdt_benchmark(s);
1734
1735 // Prepare connections for each specified remote target.
1736 vector<remote*> targets;
1737 bool fake_remote=false;
1738 if (s.remote_uris.empty())
1739 {
1740 fake_remote=true;
1741 s.remote_uris.push_back("direct:");
1742 }
1743 for (unsigned i = 0; rc == 0 && i < s.remote_uris.size(); ++i)
1744 {
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);
1748 if (target)
1749 targets.push_back(target);
1750 else
1751 rc = 1;
1752 }
1753
1754
1755 #if HAVE_LANGUAGE_SERVER_SUPPORT
1756 if(s.language_server_mode){
1757 int r = s.lang_server->run();
1758 delete s.lang_server;
1759 return r;
1760 }
1761 #endif
1762
1763 // FIXME: For now, only attempt local interactive use.
1764 if (s.interactive_mode && fake_remote)
1765 {
1766 #ifdef HAVE_LIBREADLINE
1767 rc = interactive_mode (s, targets);
1768 #endif
1769 }
1770 else
1771 {
1772 if (s.build_as != "")
1773 rc = passes_1_5_build_as(s, targets);
1774 else
1775 rc = passes_1_5(s, targets);
1776 }
1777
1778 // Pass 6. Cleanup
1779 for (unsigned i = 0; i < targets.size(); ++i)
1780 delete targets[i];
1781 cleanup (s, rc);
1782
1783 assert_no_interrupts();
1784 return (rc) ? EXIT_FAILURE : EXIT_SUCCESS;
1785 }
1786 catch (const interrupt_exception& e) {
1787 // User entered ctrl-c, exit quietly.
1788 return EXIT_FAILURE;
1789 }
1790 catch (const exit_exception& e) {
1791 // Exiting for any quiet reason.
1792 return e.rc;
1793 }
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;
1798 }
1799 catch (const exception &e) {
1800 // Some other uncaught exception.
1801 cerr << e.what() << endl;
1802 return EXIT_FAILURE;
1803 }
1804 catch (...) {
1805 // Catch all other unknown exceptions.
1806 cerr << _("ERROR: caught unknown exception!") << endl;
1807 return EXIT_FAILURE;
1808 }
1809 }
1810
1811 /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
This page took 0.130092 seconds and 6 git commands to generate.