]> sourceware.org Git - systemtap.git/blob - session.cxx
PRERELEASE handling
[systemtap.git] / session.cxx
1 // session functions
2 // Copyright (C) 2010-2017 Red Hat Inc.
3 //
4 // This file is part of systemtap, and is free software. You can
5 // redistribute it and/or modify it under the terms of the GNU General
6 // Public License (GPL); either version 2, or (at your option) any
7 // later version.
8
9 #include "config.h"
10 #include "session.h"
11 #include "cache.h"
12 #include "stapregex.h"
13 #include "elaborate.h"
14 #include "translate.h"
15 #include "buildrun.h"
16 #include "coveragedb.h"
17 #include "hash.h"
18 #include "setupdwfl.h"
19 #include "task_finder.h"
20 #include "csclient.h"
21 #include "rpm_finder.h"
22 #include "util.h"
23 #include "cmdline.h"
24 #include "git_version.h"
25 #include "version.h"
26 #include "stringtable.h"
27 #include "tapsets.h"
28
29 #include <cerrno>
30 #include <cstdlib>
31 #include <thread>
32
33 extern "C" {
34 #include <getopt.h>
35 #include <limits.h>
36 #include <grp.h>
37 #include <sys/stat.h>
38 #include <sys/utsname.h>
39 #include <sys/resource.h>
40 #include <elfutils/libdwfl.h>
41 #include <elfutils/version.h>
42 #include <unistd.h>
43 #include <sys/wait.h>
44 #include <wordexp.h>
45 }
46
47 #if HAVE_NSS
48 extern "C" {
49 #include <nspr.h>
50 }
51 #endif
52
53 #include <string>
54
55 using namespace std;
56
57 /* getopt variables */
58 extern int optind;
59
60 #define PATH_TBD string("__TBD__")
61
62 #if HAVE_NSS
63 bool systemtap_session::NSPR_Initialized = false;
64 #endif
65
66 systemtap_session::systemtap_session ():
67 // NB: pointer members must be manually initialized!
68 // NB: don't forget the copy constructor too!
69 runtime_mode(kernel_runtime),
70 base_hash(0),
71 pattern_root(new match_node),
72 dfa_counter (0),
73 dfa_maxmap (0),
74 dfa_maxtag (0),
75 need_tagged_dfa (false),
76 be_derived_probes(0),
77 generic_kprobe_derived_probes(0),
78 hwbkpt_derived_probes(0),
79 perf_derived_probes(0),
80 uprobe_derived_probes(0),
81 utrace_derived_probes(0),
82 itrace_derived_probes(0),
83 task_finder_derived_probes(0),
84 timer_derived_probes(0),
85 netfilter_derived_probes(0),
86 profile_derived_probes(0),
87 mark_derived_probes(0),
88 tracepoint_derived_probes(0),
89 hrtimer_derived_probes(0),
90 procfs_derived_probes(0),
91 dynprobe_derived_probes(0),
92 python_derived_probes(0),
93 op (0), up (0),
94 sym_kprobes_text_start (0),
95 sym_kprobes_text_end (0),
96 sym_stext (0),
97 module_cache (0),
98 benchmark_sdt_loops(0),
99 benchmark_sdt_threads(0),
100 suppressed_warnings(0),
101 suppressed_errors(0),
102 warningerr_count(0),
103 target_namespaces_pid(0),
104 last_token (0)
105 {
106 struct utsname buf;
107 (void) uname (& buf);
108 kernel_release = string (buf.release);
109 release = kernel_release;
110 kernel_build_tree = "/lib/modules/" + kernel_release + "/build";
111 architecture = machine = normalize_machine(buf.machine);
112
113 for (unsigned i=0; i<5; i++) perpass_verbose[i]=0;
114 verbose = 0;
115
116 have_script = false;
117 runtime_specified = false;
118 include_arg_start = -1;
119 timing = false;
120 guru_mode = false;
121 bulk_mode = false;
122 unoptimized = false;
123 suppress_warnings = false;
124 panic_warnings = false;
125 dump_mode = systemtap_session::dump_none;
126 dump_matched_pattern = "";
127
128 #ifdef ENABLE_PROLOGUES
129 prologue_searching_mode = prologue_searching_always;
130 #else
131 prologue_searching_mode = prologue_searching_auto;
132 #endif
133
134 buffer_size = 0;
135 last_pass = 5;
136 module_name = "stap_" + lex_cast(getpid());
137 stapconf_name = "stapconf_" + lex_cast(getpid()) + ".h";
138 output_file = ""; // -o FILE
139 tmpdir_opt_set = false;
140 monitor = false;
141 monitor_interval = 1;
142 read_stdin = false;
143 save_module = false;
144 save_uprobes = false;
145 modname_given = false;
146 keep_tmpdir = false;
147 cmd = "";
148 target_pid = 0;
149 use_cache = true;
150 use_script_cache = true;
151 poison_cache = false;
152 tapset_compile_coverage = false;
153 need_uprobes = false;
154 need_unwind = false;
155 need_symbols = false;
156 need_lines = false;
157 uprobes_path = "";
158 load_only = false;
159 skip_badvars = false;
160 privilege = pr_stapdev;
161 privilege_set = false;
162 compatible = VERSION; // XXX: perhaps also process GIT_SHAID if available?
163 unwindsym_ldd = false;
164 client_options = false;
165 server_cache = NULL;
166 auto_privilege_level_msg = "";
167 auto_server_msgs.clear ();
168 use_server_on_error = false;
169 try_server_status = try_server_unset;
170 use_remote_prefix = false;
171 systemtap_v_check = false;
172 download_dbinfo = 0;
173 suppress_handler_errors = false;
174 native_build = true; // presumed
175 sysroot = "";
176 update_release_sysroot = false;
177 suppress_time_limits = false;
178 target_namespaces_pid = 0;
179 color_mode = color_auto;
180 color_errors = isatty(STDERR_FILENO) // conditions for coloring when
181 && strcmp(getenv("TERM") ?: "notdumb", "dumb"); // on auto
182 interactive_mode = false;
183 run_example = false;
184 pass_1a_complete = false;
185 timeout = 0;
186
187 // PR12443: put compiled-in / -I paths in front, to be preferred during
188 // tapset duplicate-file elimination
189 const char* s_p = getenv ("SYSTEMTAP_TAPSET");
190 if (s_p != NULL)
191 {
192 include_path.push_back (s_p);
193 }
194 else
195 {
196 include_path.push_back (string(PKGDATADIR) + "/tapset");
197 }
198
199 /* adding in the XDG_DATA_DIRS variable path,
200 * this searches in conjunction with SYSTEMTAP_TAPSET
201 * to locate stap scripts, either can be disabled if
202 * needed using env $PATH=/dev/null where $PATH is the
203 * path you want disabled
204 */
205 const char* s_p1 = getenv ("XDG_DATA_DIRS");
206 if ( s_p1 != NULL )
207 {
208 vector<string> dirs;
209 tokenize(s_p1, dirs, ":");
210 for(vector<string>::iterator i = dirs.begin(); i != dirs.end(); ++i)
211 {
212 include_path.push_back(*i + "/systemtap/tapset");
213 }
214 }
215
216 const char* s_r = getenv ("SYSTEMTAP_RUNTIME");
217 if (s_r != NULL)
218 runtime_path = s_r;
219 else
220 runtime_path = string(PKGDATADIR) + "/runtime";
221
222 const char* s_d = getenv ("SYSTEMTAP_DIR");
223 if (s_d != NULL)
224 data_path = s_d;
225 else
226 data_path = get_home_directory() + string("/.systemtap");
227 if (create_dir(data_path.c_str()) == 1)
228 {
229 const char* e = strerror (errno);
230 print_warning("failed to create systemtap data directory \"" + data_path + "\" " + e + ", disabling cache support.");
231 use_cache = use_script_cache = false;
232 }
233
234 if (use_cache)
235 {
236 cache_path = data_path + "/cache";
237 if (create_dir(cache_path.c_str()) == 1)
238 {
239 const char* e = strerror (errno);
240 print_warning("failed to create cache directory (\" " + cache_path + " \") " + e + ", disabling cache support.");
241 use_cache = use_script_cache = false;
242 }
243 }
244
245 const char* s_tc = getenv ("SYSTEMTAP_COVERAGE");
246 if (s_tc != NULL)
247 tapset_compile_coverage = true;
248
249 const char* s_kr = getenv ("SYSTEMTAP_RELEASE");
250 if (s_kr != NULL) {
251 setup_kernel_release(s_kr);
252 }
253 }
254
255 systemtap_session::systemtap_session (const systemtap_session& other,
256 const string& arch,
257 const string& kern):
258 // NB: pointer members must be manually initialized!
259 // NB: this needs to consider everything that the base ctor does,
260 // plus copying any wanted implicit fields (strings, vectors, etc.)
261 runtime_mode(other.runtime_mode),
262 base_hash(0),
263 pattern_root(new match_node),
264 user_files (other.user_files),
265 dfa_counter(0),
266 dfa_maxmap(0),
267 dfa_maxtag (0),
268 need_tagged_dfa(other.need_tagged_dfa),
269 be_derived_probes(0),
270 generic_kprobe_derived_probes(0),
271 hwbkpt_derived_probes(0),
272 perf_derived_probes(0),
273 uprobe_derived_probes(0),
274 utrace_derived_probes(0),
275 itrace_derived_probes(0),
276 task_finder_derived_probes(0),
277 timer_derived_probes(0),
278 netfilter_derived_probes(0),
279 profile_derived_probes(0),
280 mark_derived_probes(0),
281 tracepoint_derived_probes(0),
282 hrtimer_derived_probes(0),
283 procfs_derived_probes(0),
284 dynprobe_derived_probes(0),
285 python_derived_probes(0),
286 op (0), up (0),
287 sym_kprobes_text_start (0),
288 sym_kprobes_text_end (0),
289 sym_stext (0),
290 module_cache (0),
291 benchmark_sdt_loops(other.benchmark_sdt_loops),
292 benchmark_sdt_threads(other.benchmark_sdt_threads),
293 suppressed_warnings(0),
294 suppressed_errors(0),
295 warningerr_count(0),
296 target_namespaces_pid(0),
297 last_token (0)
298 {
299 release = kernel_release = kern;
300 kernel_build_tree = "/lib/modules/" + kernel_release + "/build";
301 kernel_extra_cflags = other.kernel_extra_cflags;
302 architecture = machine = normalize_machine(arch);
303 setup_kernel_release(kern.c_str());
304 native_build = false; // assumed; XXX: could be computed as in check_options()
305
306 // These are all copied in the same order as the default ctor did above.
307
308 copy(other.perpass_verbose, other.perpass_verbose + 5, perpass_verbose);
309 verbose = other.verbose;
310
311 have_script = other.have_script;
312 runtime_specified = other.runtime_specified;
313 include_arg_start = other.include_arg_start;
314 timing = other.timing;
315 guru_mode = other.guru_mode;
316 bulk_mode = other.bulk_mode;
317 unoptimized = other.unoptimized;
318 suppress_warnings = other.suppress_warnings;
319 panic_warnings = other.panic_warnings;
320 dump_mode = other.dump_mode;
321 dump_matched_pattern = other.dump_matched_pattern;
322
323 prologue_searching_mode = other.prologue_searching_mode;
324
325 buffer_size = other.buffer_size;
326 last_pass = other.last_pass;
327 module_name = other.module_name;
328 stapconf_name = other.stapconf_name;
329 output_file = other.output_file; // XXX how should multiple remotes work?
330 tmpdir_opt_set = false;
331 monitor = other.monitor;
332 monitor_interval = other.monitor_interval;
333 save_module = other.save_module;
334 save_uprobes = other.save_uprobes;
335 modname_given = other.modname_given;
336 keep_tmpdir = other.keep_tmpdir;
337 cmd = other.cmd;
338 target_pid = other.target_pid; // XXX almost surely nonsense for multiremote
339 use_cache = other.use_cache;
340 use_script_cache = other.use_script_cache;
341 poison_cache = other.poison_cache;
342 tapset_compile_coverage = other.tapset_compile_coverage;
343 need_uprobes = false;
344 need_unwind = false;
345 need_symbols = false;
346 need_lines = false;
347 uprobes_path = "";
348 load_only = other.load_only;
349 skip_badvars = other.skip_badvars;
350 privilege = other.privilege;
351 privilege_set = other.privilege_set;
352 compatible = other.compatible;
353 unwindsym_ldd = other.unwindsym_ldd;
354 client_options = other.client_options;
355 server_cache = NULL;
356 use_server_on_error = other.use_server_on_error;
357 try_server_status = other.try_server_status;
358 use_remote_prefix = other.use_remote_prefix;
359 systemtap_v_check = other.systemtap_v_check;
360 download_dbinfo = other.download_dbinfo;
361 suppress_handler_errors = other.suppress_handler_errors;
362 sysroot = other.sysroot;
363 update_release_sysroot = other.update_release_sysroot;
364 sysenv = other.sysenv;
365 suppress_time_limits = other.suppress_time_limits;
366 color_errors = other.color_errors;
367 color_mode = other.color_mode;
368 interactive_mode = other.interactive_mode;
369 run_example = other.run_example;
370 pass_1a_complete = other.pass_1a_complete;
371 timeout = other.timeout;
372
373 include_path = other.include_path;
374 runtime_path = other.runtime_path;
375
376 // NB: assuming that "other" created these already
377 data_path = other.data_path;
378 cache_path = other.cache_path;
379
380 tapset_compile_coverage = other.tapset_compile_coverage;
381
382
383 // These are fields that were left to their default ctor, but now we want to
384 // copy them from "other". In the same order as declared...
385 script_file = other.script_file;
386 cmdline_script = other.cmdline_script;
387 additional_scripts = other.additional_scripts;
388 stdin_script.str() = other.stdin_script.str();
389 c_macros = other.c_macros;
390 args = other.args;
391 kbuildflags = other.kbuildflags;
392
393 globalopts = other.globalopts;
394 modinfos = other.modinfos;
395
396 client_options_disallowed_for_unprivileged = other.client_options_disallowed_for_unprivileged;
397 server_status_strings = other.server_status_strings;
398 specified_servers = other.specified_servers;
399 server_trust_spec = other.server_trust_spec;
400 server_args = other.server_args;
401 mok_fingerprints = other.mok_fingerprints;
402
403 // HTTP client/server
404 http_servers = other.http_servers;
405
406 unwindsym_modules = other.unwindsym_modules;
407 auto_privilege_level_msg = other.auto_privilege_level_msg;
408 auto_server_msgs = other.auto_server_msgs;
409
410 create_tmp_dir();
411 }
412
413 systemtap_session::~systemtap_session ()
414 {
415 remove_tmp_dir();
416 delete_map(subsessions);
417 delete pattern_root;
418 }
419
420 const string
421 systemtap_session::module_filename() const
422 {
423 const char *suffix;
424 switch (runtime_mode)
425 {
426 case kernel_runtime:
427 suffix = ".ko";
428 break;
429 case dyninst_runtime:
430 suffix = ".so";
431 break;
432 case bpf_runtime:
433 suffix = ".bo";
434 break;
435 default:
436 abort();
437 }
438 return module_name + suffix;
439 }
440
441 #if HAVE_NSS
442 void
443 systemtap_session::NSPR_init ()
444 {
445 if (! NSPR_Initialized)
446 {
447 PR_Init (PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
448 NSPR_Initialized = true;
449 }
450 }
451 #endif // HAVE_NSS
452
453 systemtap_session*
454 systemtap_session::clone(const string& arch, const string& release)
455 {
456 const string norm_arch = normalize_machine(arch);
457 if (this->architecture == norm_arch && this->kernel_release == release)
458 return this;
459
460 systemtap_session*& s = subsessions[make_pair(norm_arch, release)];
461 if (!s)
462 s = new systemtap_session(*this, norm_arch, release);
463 return s;
464 }
465
466
467 string
468 systemtap_session::version_string ()
469 {
470 string elfutils_version1;
471 #ifdef _ELFUTILS_VERSION
472 elfutils_version1 = "0." + lex_cast(_ELFUTILS_VERSION); /* BUILD */
473 #endif
474 string elfutils_version2 = dwfl_version(NULL); /* RUN */
475
476 if (elfutils_version1 != elfutils_version2)
477 elfutils_version2 += string("/") + elfutils_version1; /* RUN/BUILD */
478
479 return string (VERSION) + "/" + elfutils_version2 + ", " + STAP_EXTENDED_VERSION;
480 }
481
482 void
483 systemtap_session::version ()
484 {
485 // PRERELEASE
486 cout << _F("Systemtap translator/driver (version %s)\n"
487 "Copyright (C) 2005-2018 Red Hat, Inc. and others\n"
488 "This is free software; see the source for copying conditions.\n",
489 version_string().c_str());
490 // PRERELEASE
491 cout << _F("tested kernel versions: %s ... %s\n", "2.6.18", "4.16");
492
493 cout << _("enabled features:")
494 #ifdef HAVE_AVAHI
495 << " AVAHI"
496 #endif
497 #ifdef HAVE_BOOST_UTILITY_STRING_REF_HPP
498 << " BOOST_STRING_REF"
499 #endif
500 #ifdef HAVE_DYNINST
501 << " DYNINST"
502 #endif
503 #ifdef HAVE_BPF_DECLS
504 << " BPF"
505 #endif
506 #ifdef HAVE_JAVA
507 << " JAVA"
508 #endif
509 #ifdef HAVE_PYTHON2_PROBES
510 << " PYTHON2"
511 #endif
512 #ifdef HAVE_PYTHON3_PROBES
513 << " PYTHON3"
514 #endif
515 #ifdef HAVE_LIBRPM
516 << " LIBRPM"
517 #endif
518 #ifdef HAVE_LIBSQLITE3
519 << " LIBSQLITE3"
520 #endif
521 #ifdef HAVE_LIBVIRT
522 << " LIBVIRT"
523 #endif
524 #ifdef HAVE_LIBXML2
525 << " LIBXML2"
526 #endif
527 #ifdef ENABLE_NLS
528 << " NLS"
529 #endif
530 #ifdef HAVE_NSS
531 << " NSS"
532 #endif
533 #ifdef ENABLE_PROLOGUES
534 << " PROLOGUES"
535 #endif
536 #ifdef HAVE_LIBREADLINE
537 << " READLINE"
538 #endif
539 << endl;
540 }
541
542 void
543 systemtap_session::usage (int exitcode)
544 {
545 // For error cases, just suggest --help, so we don't obscure
546 // the actual error message with all the help text.
547 if (exitcode != EXIT_SUCCESS)
548 {
549 clog << _("Try '--help' for more information.") << endl;
550 throw exit_exception(exitcode);
551 }
552
553 version ();
554 cout
555 << endl
556 << _F(
557 "Usage: stap [options] FILE Run script in file.\n"
558 " or: stap [options] - Run script on stdin.\n"
559 " or: stap [options] -e SCRIPT Run given script.\n"
560 " or: stap [options] -l PROBE List matching probes.\n"
561 " or: stap [options] -L PROBE List matching probes and local variables.\n"
562 " or: stap [options] --dump-probe-types List available probe types.\n"
563 " or: stap [options] --dump-probe-aliases List available probe aliases.\n"
564 " or: stap [options] --dump-functions List available functions.\n\n"
565 "Options (in %s/rc and on command line):\n"
566 " -- end of translator options, script options follow\n"
567 " -h --help show help\n"
568 " -V --version\n"
569 " show version\n"
570 " -p NUM stop after pass NUM 1-5, instead of %d\n"
571 " (parse, elaborate, translate, compile, run)\n"
572 " -v add verbosity to all passes\n"
573 " --vp {N}+ add per-pass verbosity [", data_path.c_str(), last_pass);
574 for (unsigned i=0; i<5; i++)
575 cout << (perpass_verbose[i] <= 9 ? perpass_verbose[i] : 9);
576 cout
577 << "]" << endl;
578 cout << _F(" -k keep temporary directory\n"
579 " -u unoptimized translation %s\n"
580 " -w suppress warnings %s\n"
581 " -W turn warnings into errors %s\n"
582 " -g guru mode %s\n"
583 " -P prologue-searching for function probes %s\n"
584 " -b bulk (percpu file) mode %s\n"
585 #ifdef HAVE_LIBREADLINE
586 " -i --interactive\n"
587 " interactive mode %s\n"
588 #endif
589 " -s NUM buffer size in megabytes, instead of %d\n"
590 " -I DIR look in DIR for additional .stp script files", (unoptimized ? _(" [set]") : ""),
591 (suppress_warnings ? _(" [set]") : ""), (panic_warnings ? _(" [set]") : ""),
592 (guru_mode ? _(" [set]") : ""), (prologue_searching_mode == prologue_searching_always ? _(" [set]") : ""),
593 (bulk_mode ? _(" [set]") : ""),
594 #ifdef HAVE_LIBREADLINE
595 (interactive_mode ? _(" [set]") : ""),
596 #endif
597 buffer_size);
598 if (include_path.size() == 0)
599 cout << endl;
600 else
601 cout << _(", in addition to") << endl;
602 for (unsigned i=0; i<include_path.size(); i++)
603 cout << " " << include_path[i].c_str() << endl;
604 cout
605 << _F(" -D NM=VAL emit macro definition into generated C code\n"
606 " -B NM=VAL pass option to kbuild make\n"
607 " --modinfo NM=VAL\n"
608 " include a MODULE_INFO(NM,VAL) in the generated C code\n"
609 " -G VAR=VAL set global variable to value\n"
610 //TRANSLATORS: translating 'runtime' is not advised
611 " -R DIR look in DIR for runtime, instead of\n"
612 " %s\n"
613 " -r DIR cross-compile to kernel with given build tree; or else\n"
614 " -r RELEASE cross-compile to kernel /lib/modules/RELEASE/build, instead of\n"
615 " %s\n"
616 " -a ARCH cross-compile to given architecture, instead of %s\n"
617 " -m MODULE set probe module name, instead of \n"
618 " %s\n"
619 " -o FILE send script output to file, instead of stdout. This supports\n"
620 " strftime(3) formats for FILE\n"
621 " -E SCRIPT run the SCRIPT in addition to the main script specified\n"
622 " through -e or a script file\n"
623 " -c CMD start the probes, run CMD, and exit when it finishes\n"
624 " -x PID sets target() to PID\n"
625 " -F run as on-file flight recorder with -o.\n"
626 " run as on-memory flight recorder without -o.\n"
627 " -S size[,n] set maximum of the size and the number of files.\n"
628 " -d OBJECT add unwind/symbol data for OBJECT file", runtime_path.c_str(), kernel_build_tree.c_str(), architecture.c_str(), module_name.c_str());
629 if (unwindsym_modules.size() == 0)
630 cout << endl;
631 else
632 cout << _(", in addition to") << endl;
633 {
634 vector<string> syms (unwindsym_modules.begin(), unwindsym_modules.end());
635 for (unsigned i=0; i<syms.size(); i++)
636 cout << " " << syms[i].c_str() << endl;
637 }
638 cout
639 << _F(" --ldd add unwind/symbol data for referenced user-space objects.\n"
640 " --all-modules\n"
641 " add unwind/symbol data for all loaded kernel objects.\n"
642 " -t collect probe timing information\n"
643 " -T TIME terminate the script after TIME seconds\n"
644 #ifdef HAVE_LIBSQLITE3
645 " -q generate information on tapset coverage\n"
646 #endif /* HAVE_LIBSQLITE3 */
647 " --runtime=MODE\n"
648 " set the pass-5 runtime mode, instead of kernel\n"
649 #ifdef HAVE_DYNINST
650 " --dyninst\n"
651 " shorthand for --runtime=dyninst\n"
652 #endif /* HAVE_DYNINST */
653 #ifdef HAVE_BPF_DECLS
654 " --bpf\n"
655 " shorthand for --runtime=bpf\n"
656 #endif /* HAVE_BPF_DECLS */
657 " --prologue-searching[=WHEN]\n"
658 " prologue-searching for function probes\n"
659 " --privilege=PRIVILEGE_LEVEL\n"
660 " check the script for constructs not allowed at the given privilege level\n"
661 " --unprivileged\n"
662 " equivalent to --privilege=stapusr\n"
663 " --compatible=VERSION\n"
664 " suppress incompatible language/tapset changes beyond VERSION,\n"
665 " instead of %s\n"
666 " --check-version\n"
667 " displays warnings where a syntax element may be \n"
668 " version dependent\n"
669 " --skip-badvars\n"
670 " substitute zero for bad context $variables\n"
671 " --suppress-handler-errors\n"
672 " catch all runtime errors, quietly skip probe handlers\n"
673 " --use-server[=SERVER-SPEC]\n"
674 " specify systemtap compile-servers\n"
675 " --list-servers[=PROPERTIES]\n"
676 " report on the status of the specified compile-servers:\n"
677 " all,specified,online,trusted,signer,compatible\n"
678 #if HAVE_NSS
679 " --trust-servers[=TRUST-SPEC]\n"
680 " add/revoke trust of specified compile-servers:\n"
681 " ssl,signer,all-users,revoke,no-prompt\n"
682 " --use-server-on-error[=yes/no]\n"
683 " retry compilation using a compile server upon compilation error\n"
684 #endif
685 #ifdef HAVE_HTTP_SUPPORT
686 " --use-http-server=SERVER-SPEC\n"
687 " specify systemtap http compile server\n"
688 #endif
689 " --remote=HOSTNAME\n"
690 " run pass 5 on the specified ssh host.\n"
691 " may be repeated for targeting multiple hosts.\n"
692 " --remote-prefix\n"
693 " prefix each line of remote output with a host index.\n"
694 " --tmpdir=NAME\n"
695 " specify name of temporary directory to be used.\n"
696 " --download-debuginfo[=OPTION]\n"
697 " automatically download debuginfo using ABRT.\n"
698 " yes,no,ask,<timeout value>\n"
699 " --dump-probe-types\n"
700 " show a list of available probe types.\n"
701 " --sysroot=DIR\n"
702 " specify sysroot directory where target files (executables,\n" " libraries, etc.) are located.\n"
703 " --sysenv=VAR=VALUE\n"
704 " provide an alternate value for an environment variable\n"
705 " where the value on a remote system differs. Path\n"
706 " variables (e.g. PATH, LD_LIBRARY_PATH) are assumed to be\n"
707 " relative to the sysroot.\n"
708 " --suppress-time-limits\n"
709 " disable -DSTP_OVERLOAD, -DMAXACTION, and -DMAXTRYACTION limits\n"
710 " --save-uprobes\n"
711 " save uprobes.ko to current directory if it is built from source\n"
712 " --target-namesapce=PID\n"
713 " sets the target namespaces pid to PID\n"
714 #if HAVE_MONITOR_LIBS
715 " --monitor=INTERVAL\n"
716 " enables monitor interfaces\n"
717 #endif
718 , compatible.c_str()) << endl
719 ;
720
721 time_t now;
722 time (& now);
723 struct tm* t = localtime (& now);
724 if (t && t->tm_mon*3 + t->tm_mday*173 == 0xb6)
725 cout << morehelp << endl;
726
727 throw exit_exception (exitcode);
728 }
729
730 int
731 systemtap_session::parse_cmdline (int argc, char * const argv [])
732 {
733 client_options_disallowed_for_unprivileged = "";
734 std::set<std::string> additional_unwindsym_modules;
735 struct rlimit our_rlimit;
736 bool sysroot_option_seen = false;
737 string kernel_release_value;
738
739 while (true)
740 {
741 char * num_endptr;
742 int grc = getopt_long (argc, argv, STAP_SHORT_OPTIONS, stap_long_options, NULL);
743
744 // NB: when adding new options, consider very carefully whether they
745 // should be restricted from stap clients (after --client-options)!
746
747 if (grc < 0)
748 break;
749 switch (grc)
750 {
751 case 'V':
752 version ();
753 throw exit_exception (EXIT_SUCCESS);
754
755 case 'v':
756 server_args.push_back (string ("-") + (char)grc);
757 for (unsigned i=0; i<5; i++)
758 perpass_verbose[i] ++;
759 verbose ++;
760 break;
761
762 case 'G':
763 // Make sure the global option is only composed of the
764 // following chars: [_=a-zA-Z0-9.-]
765 assert(optarg);
766 assert_regexp_match("-G parameter", optarg, "^[a-z_][a-z0-9_]*=[a-z0-9_.-]+$");
767 globalopts.push_back (string(optarg));
768 break;
769
770 case 't':
771 server_args.push_back (string ("-") + (char)grc);
772 timing = true;
773 break;
774
775 case 'w':
776 server_args.push_back (string ("-") + (char)grc);
777 suppress_warnings = true;
778 break;
779
780 case 'W':
781 server_args.push_back (string ("-") + (char)grc);
782 panic_warnings = true;
783 break;
784
785 case 'p':
786 assert(optarg);
787 last_pass = (int)strtoul(optarg, &num_endptr, 10);
788 if (*num_endptr != '\0' || last_pass < 1 || last_pass > 5)
789 {
790 cerr << _("Invalid pass number (should be 1-5).") << endl;
791 return 1;
792 }
793 server_args.push_back (string ("-") + (char)grc + optarg);
794 break;
795
796 case 'I':
797 assert(optarg);
798 if (client_options)
799 client_options_disallowed_for_unprivileged += client_options_disallowed_for_unprivileged.empty () ? "-I" : ", -I";
800 if (include_arg_start == -1)
801 include_arg_start = include_path.size ();
802 include_path.push_back (string (optarg));
803 break;
804
805 case 'd':
806 assert(optarg);
807 server_args.push_back (string ("-") + (char)grc + optarg);
808 {
809 // Make sure an empty data object wasn't specified (-d "")
810 if (strlen (optarg) == 0)
811 {
812 cerr << _("Data object (-d) cannot be empty.") << endl;
813 return 1;
814 }
815 // At runtime user module names are resolved through their
816 // canonical (absolute) path, or else it's a kernel module name.
817 // The sysroot option might change the path to a user module.
818 additional_unwindsym_modules.insert (resolve_path (optarg));
819 // NB: we used to enable_vma_tracker() here for PR10228, but now
820 // we'll leave that to pragma:vma functions which actually use it.
821 break;
822 }
823
824 case 'e':
825 assert(optarg);
826 if (have_script)
827 {
828 cerr << _("Only one script can be given on the command line.")
829 << endl;
830 return 1;
831 }
832 server_args.push_back (string ("-") + (char)grc + optarg);
833 cmdline_script = string (optarg);
834 have_script = true;
835 break;
836
837 case 'E':
838 assert(optarg);
839 server_args.push_back (string("-") + (char)grc + optarg);
840 additional_scripts.push_back(string (optarg));
841 // don't set have_script to true, since this script is meant to be
842 // given in addition to a script/script_file.
843 break;
844
845 case 'o':
846 assert(optarg);
847 // NB: client_options not a problem, since pass 1-4 does not use output_file.
848 server_args.push_back (string ("-") + (char)grc + optarg);
849 output_file = string (optarg);
850 break;
851
852 case 'R':
853 assert(optarg);
854 if (client_options) { cerr << _F("ERROR: %s invalid with %s", "-R", "--client-options") << endl; return 1; }
855 runtime_specified = true;
856 runtime_path = string (optarg);
857 break;
858
859 case 'm':
860 assert(optarg);
861 if (client_options)
862 client_options_disallowed_for_unprivileged += client_options_disallowed_for_unprivileged.empty () ? "-m" : ", -m";
863 module_name = string (optarg);
864 save_module = true;
865 modname_given = true;
866 {
867 // If the module name ends with '.ko', chop it off since
868 // modutils doesn't like modules named 'foo.ko.ko'.
869 if (endswith(module_name, ".ko") || endswith(module_name, ".so"))
870 {
871 module_name.erase(module_name.size() - 3);
872 cerr << _F("Truncating module name to '%s'", module_name.c_str()) << endl;
873 }
874
875 // Make sure an empty module name wasn't specified (-m "")
876 if (module_name.empty())
877 {
878 cerr << _("Module name cannot be empty.") << endl;
879 return 1;
880 }
881
882 // Make sure the module name is only composed of the
883 // following chars: [a-z0-9_]
884 assert_regexp_match("-m parameter", module_name, "^[a-z0-9_]+$");
885
886 // Make sure module name isn't too long.
887 if (module_name.size() >= (MODULE_NAME_LEN - 1))
888 {
889 module_name.resize(MODULE_NAME_LEN - 1);
890 cerr << _F("Truncating module name to '%s'", module_name.c_str()) << endl;
891 }
892 }
893
894 server_args.push_back (string ("-") + (char)grc + optarg);
895 use_script_cache = false;
896 break;
897
898 case 'r':
899 assert(optarg);
900 if (client_options) // NB: no paths!
901 // Note that '-' must come last in a regex bracket expression.
902 assert_regexp_match("-r parameter from client", optarg, "^[a-z0-9_.+-]+$");
903 server_args.push_back (string ("-") + (char)grc + optarg);
904 kernel_release_value = optarg;
905 break;
906
907 case 'a':
908 assert(optarg);
909 assert_regexp_match("-a parameter", optarg, "^[a-z0-9_-]+$");
910 server_args.push_back (string ("-") + (char)grc + optarg);
911 architecture = string(optarg);
912 break;
913
914 case 'k':
915 if (client_options) { cerr << _F("ERROR: %s invalid with %s", "-k", "--client-options") << endl; return 1; }
916 keep_tmpdir = true;
917 use_script_cache = false; /* User wants to keep a usable build tree. */
918 break;
919
920 case 'g':
921 server_args.push_back (string ("-") + (char)grc);
922 guru_mode = true;
923 break;
924
925 case 'i':
926 case LONG_OPT_INTERACTIVE:
927 #ifdef HAVE_LIBREADLINE
928 if (client_options) { cerr << _F("ERROR: %s invalid with %s", "-i", "--client-options") << endl; return 1; }
929 interactive_mode = true;
930 #endif
931 break;
932
933 case 'P':
934 server_args.push_back (string ("-") + (char)grc);
935 prologue_searching_mode = prologue_searching_always;
936 break;
937
938 case 'b':
939 server_args.push_back (string ("-") + (char)grc);
940 bulk_mode = true;
941 break;
942
943 case 'u':
944 server_args.push_back (string ("-") + (char)grc);
945 unoptimized = true;
946 break;
947
948 case 's':
949 assert(optarg);
950 buffer_size = (int) strtoul (optarg, &num_endptr, 10);
951 if (*num_endptr != '\0' || buffer_size < 1 || buffer_size > 4095)
952 {
953 cerr << _("Invalid buffer size (should be 1-4095).") << endl;
954 return 1;
955 }
956 server_args.push_back (string ("-") + (char)grc + optarg);
957 break;
958
959 case 'c':
960 assert(optarg);
961 cmd = string (optarg);
962 if (cmd == "")
963 {
964 // This would mess with later code deciding to pass -c
965 // through to staprun
966 cerr << _("Empty CMD string invalid.") << endl;
967 return 1;
968 }
969 server_args.push_back (string ("-") + (char)grc + optarg);
970 break;
971
972 case 'x':
973 assert(optarg);
974 target_pid = (int) strtoul(optarg, &num_endptr, 10);
975 if (*num_endptr != '\0')
976 {
977 cerr << _("Invalid target process ID number.") << endl;
978 return 1;
979 }
980 server_args.push_back (string ("-") + (char)grc + optarg);
981 break;
982
983 case 'D':
984 assert(optarg);
985 assert_regexp_match ("-D parameter", optarg, "^[a-z_][a-z_0-9]*(=-?[a-z_0-9]+)?$");
986 if (client_options)
987 client_options_disallowed_for_unprivileged += client_options_disallowed_for_unprivileged.empty () ? "-D" : ", -D";
988 server_args.push_back (string ("-") + (char)grc + optarg);
989 c_macros.push_back (string (optarg));
990 break;
991
992 case 'S':
993 assert(optarg);
994 assert_regexp_match ("-S parameter", optarg, "^[0-9]+(,[0-9]+)?$");
995 server_args.push_back (string ("-") + (char)grc + optarg);
996 size_option = string (optarg);
997 break;
998
999 case 'T':
1000 assert(optarg);
1001 timeout = (int) 1000*strtod(optarg, &num_endptr); // convert to ms
1002 if (*num_endptr != '\0' || timeout < 1)
1003 {
1004 cerr << _("Invalid timeout interval.") << endl;
1005 return 1;
1006 }
1007 break;
1008
1009 case 'q':
1010 if (client_options) { cerr << _F("ERROR: %s invalid with %s", "-q", "--client-options") << endl; return 1; }
1011 server_args.push_back (string ("-") + (char)grc);
1012 tapset_compile_coverage = true;
1013 break;
1014
1015 case 'h':
1016 usage (0);
1017 break;
1018
1019 case 'L':
1020 if (dump_mode)
1021 {
1022 cerr << _("ERROR: only one of the -l/-L/--dump-* "
1023 "switches may be specified") << endl;
1024 return 1;
1025 }
1026 assert(optarg);
1027 server_args.push_back (string ("-") + (char)grc + optarg);
1028 dump_mode = systemtap_session::dump_matched_probes_vars;
1029 dump_matched_pattern = optarg;
1030 unoptimized = true; // This causes retention of vars for listing
1031 suppress_warnings = true;
1032 break;
1033
1034 case 'l':
1035 if (dump_mode)
1036 {
1037 cerr << _("ERROR: only one of the -l/-L/--dump-* "
1038 "switches may be specified") << endl;
1039 return 1;
1040 }
1041 assert(optarg);
1042 server_args.push_back (string ("-") + (char)grc + optarg);
1043 dump_mode = systemtap_session::dump_matched_probes;
1044 dump_matched_pattern = optarg;
1045 suppress_warnings = true;
1046 break;
1047
1048 case 'F':
1049 server_args.push_back (string ("-") + (char)grc);
1050 load_only = true;
1051 break;
1052
1053 case 'B':
1054 if (client_options) { cerr << _F("ERROR: %s invalid with %s", "-B", "--client-options") << endl; return 1; }
1055 assert(optarg);
1056 server_args.push_back (string ("-") + (char)grc + optarg);
1057 kbuildflags.push_back (string (optarg));
1058 break;
1059
1060 case LONG_OPT_VERSION:
1061 version ();
1062 throw exit_exception (EXIT_SUCCESS);
1063
1064 case LONG_OPT_VERBOSE_PASS:
1065 {
1066 assert(optarg);
1067 bool ok = true;
1068 if (strlen(optarg) < 1 || strlen(optarg) > 5)
1069 ok = false;
1070 if (ok)
1071 {
1072 for (unsigned i=0; i<strlen(optarg); i++)
1073 if (isdigit (optarg[i]))
1074 perpass_verbose[i] += optarg[i]-'0';
1075 else
1076 ok = false;
1077 }
1078 if (! ok)
1079 {
1080 cerr << _("Invalid --vp argument: it takes 1 to 5 digits.") << endl;
1081 return 1;
1082 }
1083 // NB: we don't do this: last_pass = strlen(optarg);
1084 server_args.push_back ("--vp=" + string(optarg));
1085 break;
1086 }
1087
1088 case LONG_OPT_SKIP_BADVARS:
1089 server_args.push_back ("--skip-badvars");
1090 skip_badvars = true;
1091 break;
1092
1093 case LONG_OPT_PRIVILEGE:
1094 {
1095 // We allow only multiple privilege-setting options if they all specify the same
1096 // privilege level. The server also expects and depends on this behaviour when
1097 // examining the client-side options passed to it.
1098 privilege_t newPrivilege;
1099 assert(optarg);
1100 if (strcmp (optarg, "stapdev") == 0)
1101 newPrivilege = pr_stapdev;
1102 else if (strcmp (optarg, "stapsys") == 0)
1103 newPrivilege = pr_stapsys;
1104 else if (strcmp (optarg, "stapusr") == 0)
1105 newPrivilege = pr_stapusr;
1106 else
1107 {
1108 cerr << _F("Invalid argument '%s' for --privilege.", optarg) << endl;
1109 return 1;
1110 }
1111 if (privilege_set && newPrivilege != privilege)
1112 {
1113 cerr << _("Privilege level may be set only once.") << endl;
1114 return 1;
1115 }
1116 privilege = newPrivilege;
1117 privilege_set = true;
1118 server_args.push_back ("--privilege=" + string(optarg));
1119 }
1120 /* NB: for server security, it is essential that once this flag is
1121 set, no future flag be able to unset it. */
1122 break;
1123
1124 case LONG_OPT_UNPRIVILEGED:
1125 // We allow only multiple privilege-setting options if they all specify the same
1126 // privilege level. The server also expects and depends on this behaviour when
1127 // examining the client-side options passed to it.
1128 if (privilege_set && pr_unprivileged != privilege)
1129 {
1130 cerr << _("Privilege level may be set only once.") << endl;
1131 return 1;
1132 }
1133 privilege = pr_unprivileged;
1134 privilege_set = true;
1135 server_args.push_back ("--unprivileged");
1136 /* NB: for server security, it is essential that once this flag is
1137 set, no future flag be able to unset it. */
1138 break;
1139
1140 case LONG_OPT_CLIENT_OPTIONS:
1141 client_options = true;
1142 break;
1143
1144 case LONG_OPT_TMPDIR:
1145 if (client_options) {
1146 cerr << _F("ERROR: %s is invalid with %s", "--tmpdir", "--client-options") << endl;
1147 return 1;
1148 }
1149 tmpdir_opt_set = true;
1150 tmpdir = optarg;
1151 break;
1152
1153 case LONG_OPT_DOWNLOAD_DEBUGINFO:
1154 if(optarg)
1155 {
1156 if(strcmp(optarg, "no") == 0)
1157 download_dbinfo = 0; //Disable feature
1158 else if (strcmp(optarg, "yes") == 0)
1159 download_dbinfo = INT_MAX; //Enable, No Timeout
1160 /* NOTE: Timeout and Asking for Confirmation features below are not supported yet by abrt
1161 * in version abrt-2.0.3-1.fc15.x86_64, Bugzilla: BZ730107 (timeout), BZ726192 ('-y') */
1162 else if(atoi(optarg) > 0)
1163 download_dbinfo = atoi(optarg); //Enable, Set timeout to optarg
1164 else if (strcmp(optarg, "ask") == 0)
1165 download_dbinfo = -1; //Enable, Ask for confirmation
1166 else
1167 {
1168 cerr << _F("ERROR: %s is not a valid value. Use 'yes', 'no', 'ask' or a timeout value.", optarg) << endl;
1169 return 1;
1170 }
1171 }
1172 else
1173 download_dbinfo = INT_MAX; //Enable, No Timeout
1174 break;
1175
1176 case LONG_OPT_USE_SERVER:
1177 if (client_options) {
1178 cerr << _F("ERROR: %s is invalid with %s", "--use-server", "--client-options") << endl;
1179 return 1;
1180 }
1181 if (optarg)
1182 specified_servers.push_back (optarg);
1183 else
1184 specified_servers.push_back ("");
1185 break;
1186
1187 case LONG_OPT_USE_SERVER_ON_ERROR:
1188 if (client_options) {
1189 cerr << _F("ERROR: %s is invalid with %s", "--use-server-on-error", "--client-options") << endl;
1190 return 1;
1191 }
1192 if (optarg)
1193 {
1194 string arg = optarg;
1195 for (unsigned i = 0; i < arg.size (); ++i)
1196 arg[i] = tolower (arg[i]);
1197 if (arg == "yes" || arg == "ye" || arg == "y")
1198 use_server_on_error = true;
1199 else if (arg == "no" || arg == "n")
1200 use_server_on_error = false;
1201 else
1202 cerr << _F("Invalid argument '%s' for --use-server-on-error.", optarg) << endl;
1203 }
1204 else
1205 use_server_on_error = true;
1206 break;
1207
1208 case LONG_OPT_LIST_SERVERS:
1209 if (client_options) {
1210 cerr << _F("ERROR: %s is invalid with %s", "--list-servers", "--client-options") << endl;
1211 return 1;
1212 }
1213 if (optarg)
1214 server_status_strings.push_back (optarg);
1215 else
1216 server_status_strings.push_back ("");
1217 break;
1218
1219 case LONG_OPT_TRUST_SERVERS:
1220 if (client_options) {
1221 cerr << _F("ERROR: %s is invalid with %s", "--trust-servers", "--client-options") << endl;
1222 return 1;
1223 }
1224 if (optarg)
1225 server_trust_spec = optarg;
1226 else
1227 server_trust_spec = "ssl";
1228 break;
1229
1230
1231 #ifdef HAVE_HTTP_SUPPORT
1232 case LONG_OPT_USE_HTTP_SERVER:
1233 if (client_options) {
1234 cerr << _F("ERROR: %s is invalid with %s", "--use-http-server", "--client-options") << endl;
1235 return 1;
1236 }
1237 http_servers.push_back (optarg);
1238 break;
1239 #endif
1240
1241 case LONG_OPT_HELP:
1242 usage (0);
1243 break;
1244
1245 case LONG_OPT_RUN_EXAMPLE:
1246 run_example = true;
1247 break;
1248
1249 // The caching options should not be available to server clients
1250 case LONG_OPT_DISABLE_CACHE:
1251 if (client_options) {
1252 cerr << _F("ERROR: %s is invalid with %s", "--disable-cache", "--client-options") << endl;
1253 return 1;
1254 }
1255 use_cache = use_script_cache = false;
1256 break;
1257
1258 case LONG_OPT_POISON_CACHE:
1259 if (client_options) {
1260 cerr << _F("ERROR: %s is invalid with %s", "--poison-cache", "--client-options") << endl;
1261 return 1;
1262 }
1263 poison_cache = true;
1264 break;
1265
1266 case LONG_OPT_CLEAN_CACHE:
1267 if (client_options) {
1268 cerr << _F("ERROR: %s is invalid with %s", "--clean-cache", "--client-options") << endl;
1269 return 1;
1270 }
1271 clean_cache(*this);
1272 throw exit_exception(EXIT_SUCCESS);
1273
1274 case LONG_OPT_COMPATIBLE:
1275 assert(optarg);
1276 server_args.push_back ("--compatible=" + string(optarg));
1277 if (strverscmp(optarg, VERSION) > 0) {
1278 cerr << _F("ERROR: systemtap version %s cannot be compatible with future version %s", VERSION, optarg)
1279 << endl;
1280 return 1;
1281 }
1282 compatible = optarg;
1283 break;
1284
1285 case LONG_OPT_LDD:
1286 if (client_options) {
1287 cerr << _F("ERROR: %s is invalid with %s", "--ldd", "--client-options") << endl;
1288 return 1;
1289 }
1290 unwindsym_ldd = true;
1291 break;
1292
1293 case LONG_OPT_ALL_MODULES:
1294 if (client_options) {
1295 cerr << _F("ERROR: %s is invalid with %s", "--all-modules", "--client-options") << endl;
1296 return 1;
1297 }
1298 insert_loaded_modules();
1299 break;
1300
1301 case LONG_OPT_REMOTE:
1302 if (client_options) {
1303 cerr << _F("ERROR: %s is invalid with %s", "--remote", "--client-options") << endl;
1304 return 1;
1305 }
1306
1307 remote_uris.push_back(optarg);
1308 break;
1309
1310 case LONG_OPT_REMOTE_PREFIX:
1311 if (client_options) {
1312 cerr << _F("ERROR: %s is invalid with %s", "--remote-prefix", "--client-options") << endl;
1313 return 1;
1314 }
1315
1316 use_remote_prefix = true;
1317 break;
1318
1319 case LONG_OPT_CHECK_VERSION:
1320 server_args.push_back ("--check-version");
1321 systemtap_v_check = true;
1322 break;
1323
1324 case LONG_OPT_DUMP_PROBE_TYPES:
1325 if (dump_mode)
1326 {
1327 cerr << _("ERROR: only one of the -l/-L/--dump-* "
1328 "switches may be specified") << endl;
1329 return 1;
1330 }
1331 server_args.push_back ("--dump-probe-types");
1332 dump_mode = systemtap_session::dump_probe_types;
1333 break;
1334
1335 case LONG_OPT_DUMP_PROBE_ALIASES:
1336 if (dump_mode)
1337 {
1338 cerr << _("ERROR: only one of the -l/-L/--dump-* "
1339 "switches may be specified") << endl;
1340 return 1;
1341 }
1342 server_args.push_back ("--dump-probe-aliases");
1343 suppress_warnings = true;
1344 dump_mode = systemtap_session::dump_probe_aliases;
1345 break;
1346
1347 case LONG_OPT_DUMP_FUNCTIONS:
1348 if (dump_mode)
1349 {
1350 cerr << _("ERROR: only one of the -l/-L/--dump-* "
1351 "switches may be specified") << endl;
1352 return 1;
1353 }
1354 server_args.push_back ("--dump-functions");
1355 suppress_warnings = true;
1356 dump_mode = systemtap_session::dump_functions;
1357 unoptimized = true; // Keep unused functions (which is all of them)
1358 break;
1359
1360 case LONG_OPT_SUPPRESS_HANDLER_ERRORS:
1361 suppress_handler_errors = true;
1362 c_macros.push_back (string ("STAP_SUPPRESS_HANDLER_ERRORS"));
1363 break;
1364
1365 case LONG_OPT_MODINFO:
1366 // Make sure the global option is only composed of the
1367 // following chars: [_=a-zA-Z0-9]
1368 if (client_options) {
1369 cerr << _F("ERROR: %s is invalid with %s", "--modinfo", "--client-options") << endl;
1370 return 1;
1371 }
1372 assert(optarg);
1373 assert_regexp_match("--modinfo parameter", optarg, "^[a-z_][a-z0-9_]*=.+$");
1374 modinfos.push_back (string(optarg));
1375 break;
1376
1377 case LONG_OPT_RLIMIT_AS:
1378 assert(optarg);
1379 if(getrlimit(RLIMIT_AS, & our_rlimit))
1380 cerr << _F("Unable to obtain resource limits for rlimit-as : %s", strerror (errno)) << endl;
1381 if (strlen(optarg) == 0) {
1382 cerr << _("An --rlimit-as option value must be specified.") << endl;
1383 return 1;
1384 }
1385 our_rlimit.rlim_max = our_rlimit.rlim_cur = strtoul (optarg, &num_endptr, 0);
1386 if(*num_endptr) {
1387 cerr << _F("Unable to convert rlimit-as resource limit '%s'.", optarg) << endl;
1388 return 1;
1389 }
1390 if(setrlimit (RLIMIT_AS, & our_rlimit)) {
1391 int saved_errno = errno;
1392 cerr << _F("Unable to set resource limits for rlimit-as : %s", strerror (errno)) << endl;
1393 if (saved_errno != EPERM)
1394 return 1;
1395 }
1396
1397 /* Disable core dumps, since exhaustion results in uncaught bad_alloc etc. exceptions */
1398 our_rlimit.rlim_max = our_rlimit.rlim_cur = 0;
1399 (void) setrlimit (RLIMIT_CORE, & our_rlimit);
1400 break;
1401
1402 case LONG_OPT_RLIMIT_CPU:
1403 assert(optarg);
1404 if(getrlimit(RLIMIT_CPU, & our_rlimit))
1405 cerr << _F("Unable to obtain resource limits for rlimit-cpu : %s", strerror (errno)) << endl;
1406 if (strlen(optarg) == 0) {
1407 cerr << _("An --rlimit-cpu option value must be specified.") << endl;
1408 return 1;
1409 }
1410 our_rlimit.rlim_max = our_rlimit.rlim_cur = strtoul (optarg, &num_endptr, 0);
1411 if(*num_endptr) {
1412 cerr << _F("Unable to convert resource limit '%s' for rlimit-cpu", optarg) << endl;
1413 return 1;
1414 }
1415 if(setrlimit (RLIMIT_CPU, & our_rlimit)) {
1416 int saved_errno = errno;
1417 cerr << _F("Unable to set resource limits for rlimit-cpu : %s", strerror (errno)) << endl;
1418 if (saved_errno != EPERM)
1419 return 1;
1420 }
1421 break;
1422
1423 case LONG_OPT_RLIMIT_NPROC:
1424 assert(optarg);
1425 if(getrlimit(RLIMIT_NPROC, & our_rlimit))
1426 cerr << _F("Unable to obtain resource limits for rlimit-nproc : %s", strerror (errno)) << endl;
1427 if (strlen(optarg) == 0) {
1428 cerr << _("An --rlimit-nproc option value must be specified.") << endl;
1429 return 1;
1430 }
1431 our_rlimit.rlim_max = our_rlimit.rlim_cur = strtoul (optarg, &num_endptr, 0);
1432 if(*num_endptr) {
1433 cerr << _F("Unable to convert resource limit '%s' for rlimit-nproc", optarg) << endl;
1434 return 1;
1435 }
1436 if(setrlimit (RLIMIT_NPROC, & our_rlimit)) {
1437 int saved_errno = errno;
1438 cerr << _F("Unable to set resource limits for rlimit-nproc : %s", strerror (errno)) << endl;
1439 if (saved_errno != EPERM)
1440 return 1;
1441 }
1442 break;
1443
1444 case LONG_OPT_RLIMIT_STACK:
1445 assert(optarg);
1446 if(getrlimit(RLIMIT_STACK, & our_rlimit))
1447 cerr << _F("Unable to obtain resource limits for rlimit-stack : %s", strerror (errno)) << endl;
1448 if (strlen(optarg) == 0) {
1449 cerr << _("An --rlimit-stack option value must be specified.") << endl;
1450 return 1;
1451 }
1452 our_rlimit.rlim_max = our_rlimit.rlim_cur = strtoul (optarg, &num_endptr, 0);
1453 if(*num_endptr) {
1454 cerr << _F("Unable to convert resource limit '%s' for rlimit-stack", optarg) << endl;
1455 return 1;
1456 }
1457 if(setrlimit (RLIMIT_STACK, & our_rlimit)) {
1458 int saved_errno = errno;
1459 cerr << _F("Unable to set resource limits for rlimit-stack : %s", strerror (errno)) << endl;
1460 if (saved_errno != EPERM)
1461 return 1;
1462 }
1463
1464 /* Disable core dumps, since exhaustion results in SIGSEGV */
1465 our_rlimit.rlim_max = our_rlimit.rlim_cur = 0;
1466 (void) setrlimit (RLIMIT_CORE, & our_rlimit);
1467 break;
1468
1469 case LONG_OPT_RLIMIT_FSIZE:
1470 assert(optarg);
1471 if(getrlimit(RLIMIT_FSIZE, & our_rlimit))
1472 cerr << _F("Unable to obtain resource limits for rlimit-fsize : %s", strerror (errno)) << endl;
1473 if (strlen(optarg) == 0) {
1474 cerr << _("An --rlimit-fsize option value must be specified.") << endl;
1475 return 1;
1476 }
1477 our_rlimit.rlim_max = our_rlimit.rlim_cur = strtoul (optarg, &num_endptr, 0);
1478 if(*num_endptr) {
1479 cerr << _F("Unable to convert resource limit '%s' for rlimit-fsize", optarg) << endl;
1480 return 1;
1481 }
1482 if(setrlimit (RLIMIT_FSIZE, & our_rlimit)) {
1483 int saved_errno = errno;
1484 cerr << _F("Unable to set resource limits for rlimit-fsize : %s", strerror (errno)) << endl;
1485 if (saved_errno != EPERM)
1486 return 1;
1487 }
1488 break;
1489
1490 case LONG_OPT_SYSROOT:
1491 if (client_options) {
1492 cerr << _F("ERROR: %s invalid with %s", "--sysroot", "--client-options") << endl;
1493 return 1;
1494 } else if (sysroot_option_seen) {
1495 cerr << "ERROR: multiple --sysroot options not supported" << endl;
1496 return 1;
1497 } else {
1498 char *spath;
1499 assert(optarg);
1500 spath = canonicalize_file_name (optarg);
1501 if (spath == NULL) {
1502 cerr << _F("ERROR: %s is an invalid directory for --sysroot", optarg) << endl;
1503 return 1;
1504 }
1505
1506 sysroot = string(spath);
1507 free (spath);
1508
1509 // We do path creation like this:
1510 // sysroot + "/lib/modules"
1511 // So, we don't want the sysroot path to end with a '/',
1512 // otherwise we'll end up with '/foo//lib/modules'.
1513 if (!sysroot.empty() && *(sysroot.end() - 1) == '/') {
1514 sysroot.erase(sysroot.end() - 1);
1515 }
1516 }
1517 sysroot_option_seen = true;
1518 break;
1519
1520 case LONG_OPT_SYSENV:
1521 if (client_options) {
1522 cerr << _F("ERROR: %s invalid with %s", "--sysenv", "--client-options") << endl;
1523 return 1;
1524 } else {
1525 string sysenv_str = optarg;
1526 string value;
1527 size_t pos;
1528 if (! sysroot_option_seen) {
1529 cerr << "ERROR: --sysenv must follow --sysroot" << endl;
1530 return 1;
1531 }
1532
1533 pos = sysenv_str.find("=");
1534 if (pos == string::npos) {
1535 cerr << _F("ERROR: %s is an invalid argument for --sysenv", optarg) << endl;
1536 return 1;
1537 }
1538
1539 value = sysenv_str.substr(pos + 1);
1540 sysenv[sysenv_str.substr(0, pos)] = value;
1541
1542 break;
1543 }
1544
1545 case LONG_OPT_SUPPRESS_TIME_LIMITS: //require guru_mode to use
1546 if (guru_mode == false)
1547 {
1548 cerr << _F("ERROR %s requires guru mode (-g)", "--suppress-time-limits") << endl;
1549 return 1;
1550 }
1551 else
1552 {
1553 suppress_time_limits = true;
1554 server_args.push_back (string ("--suppress-time-limits"));
1555 c_macros.push_back (string ("STAP_SUPPRESS_TIME_LIMITS_ENABLE"));
1556 break;
1557 }
1558
1559 case LONG_OPT_RUNTIME:
1560 if (!parse_cmdline_runtime (optarg))
1561 return 1;
1562 break;
1563
1564 case LONG_OPT_RUNTIME_DYNINST:
1565 if (!parse_cmdline_runtime ("dyninst"))
1566 return 1;
1567 break;
1568
1569 case LONG_OPT_RUNTIME_BPF:
1570 if (!parse_cmdline_runtime ("bpf"))
1571 return 1;
1572 break;
1573
1574 case LONG_OPT_BENCHMARK_SDT:
1575 // XXX This option is secret, not supported, subject to change at our whim
1576 benchmark_sdt_threads = thread::hardware_concurrency();
1577 break;
1578
1579 case LONG_OPT_BENCHMARK_SDT_LOOPS:
1580 assert(optarg != 0); // optarg can't be NULL (or getopt would choke)
1581 // XXX This option is secret, not supported, subject to change at our whim
1582 benchmark_sdt_loops = strtoul(optarg, NULL, 10);
1583 break;
1584
1585 case LONG_OPT_BENCHMARK_SDT_THREADS:
1586 assert(optarg != 0); // optarg can't be NULL (or getopt would choke)
1587 // XXX This option is secret, not supported, subject to change at our whim
1588 benchmark_sdt_threads = strtoul(optarg, NULL, 10);
1589 break;
1590
1591 case LONG_OPT_COLOR_ERRS:
1592 // --color without arg is equivalent to always
1593 if (!optarg || !strcmp(optarg, "always"))
1594 color_mode = color_always;
1595 else if (!strcmp(optarg, "auto"))
1596 color_mode = color_auto;
1597 else if (!strcmp(optarg, "never"))
1598 color_mode = color_never;
1599 else {
1600 cerr << _F("Invalid argument '%s' for --color.", optarg) << endl;
1601 return 1;
1602 }
1603 color_errors = color_mode == color_always
1604 || (color_mode == color_auto && isatty(STDERR_FILENO) &&
1605 strcmp(getenv("TERM") ?: "notdumb", "dumb"));
1606 break;
1607
1608 case LONG_OPT_PROLOGUE_SEARCHING:
1609 // --prologue-searching without arg is equivalent to always
1610 if (!optarg || !strcmp(optarg, "always"))
1611 prologue_searching_mode = prologue_searching_always;
1612 else if (!strcmp(optarg, "auto"))
1613 prologue_searching_mode = prologue_searching_auto;
1614 else if (!strcmp(optarg, "never"))
1615 prologue_searching_mode = prologue_searching_never;
1616 else {
1617 cerr << _F("Invalid argument '%s' for --prologue-searching.", optarg) << endl;
1618 return 1;
1619 }
1620 break;
1621
1622 case LONG_OPT_SAVE_UPROBES:
1623 save_uprobes = true;
1624 break;
1625
1626 case LONG_OPT_TARGET_NAMESPACES:
1627 assert(optarg);
1628 target_namespaces_pid = (int) strtoul(optarg, &num_endptr, 10);
1629 if (*num_endptr != '\0' || target_namespaces_pid < 1)
1630 {
1631 cerr << _("Invalid process ID number for target namespaces.") << endl;
1632 return 1;
1633 }
1634 break;
1635
1636 case LONG_OPT_MONITOR:
1637 monitor = true;
1638 if (optarg)
1639 {
1640 monitor_interval = (int) strtoul(optarg, &num_endptr, 10);
1641 if (*num_endptr != '\0' || monitor_interval < 1)
1642 {
1643 cerr << _("Invalid monitor interval.") << endl;
1644 return 1;
1645 }
1646 }
1647 break;
1648
1649 case '?':
1650 // Invalid/unrecognized option given or argument required, but
1651 // not given. In both cases getopt_long() will have printed the
1652 // appropriate error message to stderr already.
1653 usage(1);
1654 break;
1655
1656 default:
1657 // NOTREACHED unless one added a getopt option but not a corresponding case:
1658 cerr << _F("Unhandled argument code %d", (char)grc) << endl;
1659 return 1;
1660 break;
1661 }
1662 }
1663
1664 for (std::set<std::string>::iterator it = additional_unwindsym_modules.begin();
1665 it != additional_unwindsym_modules.end();
1666 it++)
1667 {
1668 if (is_user_module(*it))
1669 {
1670 unwindsym_modules.insert (resolve_path(sysroot + *it));
1671 }
1672 else
1673 {
1674 unwindsym_modules.insert (*it);
1675 }
1676 }
1677
1678 if (! kernel_release_value.empty())
1679 {
1680 setup_kernel_release(kernel_release_value);
1681 }
1682 else if (! sysroot.empty())
1683 {
1684 kernel_build_tree = sysroot + "/lib/modules/" + kernel_release + "/build";
1685 }
1686
1687 return 0;
1688 }
1689
1690 bool
1691 systemtap_session::parse_cmdline_runtime (const string& opt_runtime)
1692 {
1693 if (opt_runtime == string("kernel"))
1694 runtime_mode = kernel_runtime;
1695 else if (opt_runtime == string("bpf"))
1696 {
1697 #ifndef HAVE_BPF_DECLS
1698 cerr << _("ERROR: --runtime=bpf unavailable; this build lacks BPF feature") << endl;
1699 version();
1700 return false;
1701 #else
1702 runtime_mode = bpf_runtime;
1703 use_cache = use_script_cache = false;
1704 #endif
1705 }
1706 else if (opt_runtime == string("dyninst"))
1707 {
1708 #ifndef HAVE_DYNINST
1709 cerr << _("ERROR: --runtime=dyninst unavailable; this build lacks DYNINST feature") << endl;
1710 version();
1711 return false;
1712 #else
1713 if (privilege_set && pr_unprivileged != privilege)
1714 {
1715 cerr << _("ERROR: --runtime=dyninst implies unprivileged mode only") << endl;
1716 return false;
1717 }
1718 privilege = pr_unprivileged;
1719 privilege_set = true;
1720 runtime_mode = dyninst_runtime;
1721 #endif
1722 }
1723 else
1724 {
1725 cerr << _F("ERROR: %s is an invalid argument for --runtime", opt_runtime.c_str()) << endl;
1726 return false;
1727 }
1728
1729 return true;
1730 }
1731
1732 void
1733 systemtap_session::check_options (int argc, char * const argv [])
1734 {
1735 for (int i = optind; i < argc; i++)
1736 {
1737 if (! have_script && ! dump_mode)
1738 {
1739 script_file = string (argv[i]);
1740 have_script = true;
1741 }
1742 else
1743 args.push_back (string (argv[i]));
1744 }
1745
1746 // We don't need a script with --list-servers, --trust-servers, or any dump mode
1747 bool need_script = server_status_strings.empty () &&
1748 server_trust_spec.empty () &&
1749 !dump_mode && !interactive_mode;
1750
1751 if (benchmark_sdt_loops > 0 || benchmark_sdt_threads > 0)
1752 {
1753 // Secret benchmarking options are for local use only, not servers or --remote
1754 if (client_options || !remote_uris.empty())
1755 {
1756 cerr << _("Benchmark options are only for local use.") << endl;
1757 usage(1);
1758 }
1759
1760 // Fill defaults if either is unset.
1761 if (benchmark_sdt_loops == 0)
1762 benchmark_sdt_loops = 10000000;
1763 if (benchmark_sdt_threads == 0)
1764 benchmark_sdt_threads = 1;
1765
1766 need_script = false;
1767 }
1768
1769 // need a user file
1770 // NB: this is also triggered if stap is invoked with no arguments at all
1771 if (need_script && ! have_script)
1772 {
1773 cerr << _("A script must be specified.") << endl;
1774 cerr << _("Try '-i' for building a script interactively.") << endl;
1775 usage(1);
1776 }
1777 if (dump_mode && have_script)
1778 {
1779 cerr << _("Cannot specify a script with -l/-L/--dump-* switches.") << endl;
1780 usage(1);
1781 }
1782 if (dump_mode && last_pass != 5)
1783 {
1784 cerr << _("Cannot specify -p with -l/-L/--dump-* switches.") << endl;
1785 usage(1);
1786 }
1787 if (dump_mode && interactive_mode)
1788 {
1789 cerr << _("Cannot specify -i with -l/-L/--dump-* switches.") << endl;
1790 usage(1);
1791 }
1792 if (dump_mode && monitor)
1793 {
1794 cerr << _("Cannot specify --monitor with -l/-L/--dump-* switches.") << endl;
1795 usage(1);
1796 }
1797 // FIXME: we need to think through other options that shouldn't be
1798 // used with '-i'.
1799
1800 #if ! HAVE_NSS
1801 if (client_options)
1802 print_warning("--client-options is not supported by this version of systemtap");
1803
1804 if (! server_status_strings.empty ())
1805 {
1806 print_warning("--list-servers is not supported by this version of systemtap");
1807 server_status_strings.clear ();
1808 }
1809
1810 if (! server_trust_spec.empty ())
1811 {
1812 print_warning("--trust-servers is not supported by this version of systemtap");
1813 server_trust_spec.clear ();
1814 }
1815 #endif
1816
1817 #if ! HAVE_MONITOR_LIBS
1818 if (monitor)
1819 {
1820 print_warning("Monitor mode is not supported by this version of systemtap");
1821 exit(1);
1822 }
1823 #endif
1824
1825 if (runtime_specified && ! specified_servers.empty ())
1826 {
1827 print_warning("Ignoring --use-server due to the use of -R");
1828 specified_servers.clear ();
1829 }
1830
1831 if (client_options && last_pass > 4)
1832 {
1833 last_pass = 4; /* Quietly downgrade. Server passed through -p5 naively. */
1834 }
1835
1836 // If phase 5 has been requested, automatically adjust the --privilege setting to match the
1837 // user's actual privilege level and add --use-server, if necessary.
1838 // Do this only if we have a script and we are not the server.
1839 // Also do this only if we're running in the kernel (e.g. not --runtime=dyninst)
1840 // XXX Eventually we could check remote hosts, but disable that case for now.
1841 if (last_pass > 4 && have_script && ! client_options &&
1842 runtime_mode == kernel_runtime && remote_uris.empty())
1843 {
1844 // What is the user's privilege level?
1845 privilege_t credentials = get_privilege_credentials ();
1846 // Don't alter specifically-requested privilege levels
1847 if (! privilege_set && ! pr_contains (credentials, privilege))
1848 {
1849 // We do not have the default privilege credentials (stapdev). Lower
1850 // the privilege level to match our credentials.
1851 if (pr_contains (credentials, pr_stapsys))
1852 {
1853 privilege = pr_stapsys;
1854 server_args.push_back ("--privilege=stapsys");
1855 auto_privilege_level_msg =
1856 _("--privilege=stapsys was automatically selected because you are a member "
1857 "of the groups stapusr and stapsys. [man stap]");
1858 }
1859 else if (pr_contains (credentials, pr_stapusr))
1860 {
1861 privilege = pr_stapusr;
1862 server_args.push_back ("--privilege=stapusr");
1863 auto_privilege_level_msg =
1864 _("--privilege=stapusr was automatically selected because you are a member "
1865 "of the group stapusr. [man stap]");
1866 }
1867 else
1868 {
1869 // Completely unprivileged user.
1870 cerr << _("You are trying to run systemtap as a normal user.\n"
1871 "You should either be root, or be part of "
1872 "the group \"stapusr\" and possibly one of the groups "
1873 "\"stapsys\" or \"stapdev\". [man stap]\n");
1874 #if HAVE_DYNINST
1875 cerr << _("Alternatively, you may specify --runtime=dyninst for userspace probing.\n");
1876 #endif
1877 usage (1); // does not return.
1878 }
1879 }
1880 // Add --use-server if not already specified and the user's (lack of) credentials require
1881 // it for pass 5.
1882 if (! pr_contains (credentials, pr_stapdev))
1883 {
1884 enable_auto_server (
1885 _F("For users with the privilege level %s, the module created by compiling your "
1886 "script must be signed by a trusted systemtap compile-server. [man stap-server]",
1887 pr_name (credentials)));
1888 }
1889 }
1890
1891 if (client_options && ! pr_contains (privilege, pr_stapdev) && ! client_options_disallowed_for_unprivileged.empty ())
1892 {
1893 cerr << _F("You can't specify %s when --privilege=%s is specified.",
1894 client_options_disallowed_for_unprivileged.c_str(),
1895 pr_name (privilege))
1896 << endl;
1897 usage (1);
1898 }
1899 if ((cmd != "") && (target_pid))
1900 {
1901 cerr << _F("You can't specify %s and %s together.", "-c", "-x") << endl;
1902 usage (1);
1903 }
1904
1905 // NB: In user-mode runtimes (dyninst), we can allow guru mode any time, but we
1906 // need to restrict guru by privilege level in the kernel runtime.
1907 if (! runtime_usermode_p () && ! pr_contains (privilege, pr_stapdev) && guru_mode)
1908 {
1909 cerr << _F("You can't specify %s and --privilege=%s together.", "-g", pr_name (privilege))
1910 << endl;
1911 usage (1);
1912 }
1913
1914 // Can't use --remote and --tmpdir together because with --remote,
1915 // there may be more than one tmpdir needed.
1916 if (!remote_uris.empty() && tmpdir_opt_set)
1917 {
1918 cerr << _F("You can't specify %s and %s together.", "--remote", "--tmpdir") << endl;
1919 usage(1);
1920 }
1921 // Warn in case the target kernel release doesn't match the running one.
1922 native_build = (release == kernel_release &&
1923 machine == architecture); // NB: squashed ARCH by PR4186 logic
1924
1925 // Non-native builds can't be loaded locally, but may still work on remotes
1926 if (last_pass > 4 && !native_build && remote_uris.empty())
1927 {
1928 print_warning("kernel release/architecture mismatch with host forces last-pass 4.");
1929 last_pass = 4;
1930 }
1931 if(download_dbinfo != 0 && access ("/usr/bin/abrt-action-install-debuginfo-to-abrt-cache", X_OK) < 0
1932 && access ("/usr/libexec/abrt-action-install-debuginfo-to-abrt-cache", X_OK) < 0)
1933 {
1934 print_warning("abrt-action-install-debuginfo-to-abrt-cache is not installed. Continuing without downloading debuginfo.");
1935 download_dbinfo = 0;
1936 }
1937
1938 // translate path of runtime to absolute path
1939 if (runtime_path[0] != '/')
1940 {
1941 char cwd[PATH_MAX];
1942 if (getcwd(cwd, sizeof(cwd)))
1943 {
1944 runtime_path = string(cwd) + "/" + runtime_path;
1945 }
1946 }
1947
1948 // Abnormal characters in our temp path can break us, including parts out
1949 // of our control like Kbuild. Let's enforce nice, safe characters only.
1950 const char *tmpdir = getenv("TMPDIR");
1951 if (tmpdir != NULL)
1952 assert_regexp_match("TMPDIR", tmpdir, "^[-/._0-9a-z]+$");
1953
1954 // If the kernel is using signed modules, we need to enforce server
1955 // use.
1956 if (!client_options && modules_must_be_signed())
1957 {
1958 // Force server use to be on, if not on already.
1959 enable_auto_server (
1960 _("The kernel on your system requires modules to be signed for loading.\n"
1961 "The module created by compiling your script must be signed by a systemtap "
1962 "compile-server. [man stap-server]"));
1963
1964 // Cache the current system's machine owner key (MOK)
1965 // information, to pass over to the server.
1966 get_mok_info();
1967 }
1968 }
1969
1970 int
1971 systemtap_session::parse_kernel_config ()
1972 {
1973 // PR10702: pull config options
1974 string kernel_config_file = kernel_build_tree + "/.config";
1975 struct stat st;
1976 int rc = stat(kernel_config_file.c_str(), &st);
1977 if (rc != 0)
1978 {
1979 clog << _F("Checking \"%s\" failed with error: %s",
1980 kernel_config_file.c_str(), strerror(errno)) << endl;
1981 find_devel_rpms(*this, kernel_build_tree.c_str());
1982 // Enable warnings, so that the rpm-installation help is sent
1983 // out. The above message is going to go to stderr anyway
1984 // in the case of stap -L without a necessary -devel available.
1985 // Might as well make the text more helpful.
1986 this->suppress_warnings = false;
1987 missing_rpm_list_print(*this, "-devel");
1988 return rc;
1989 }
1990
1991 ifstream kcf (kernel_config_file.c_str());
1992 string line;
1993 while (getline (kcf, line))
1994 {
1995 if (!startswith(line, "CONFIG_")) continue;
1996 size_t off = line.find('=');
1997 if (off == string::npos) continue;
1998 string key = line.substr(0, off);
1999 string value = line.substr(off+1, string::npos);
2000 kernel_config[key] = value;
2001 }
2002 if (verbose > 2)
2003 clog << _F("Parsed kernel \"%s\", ", kernel_config_file.c_str())
2004 << _NF("containing %zu tuple", "containing %zu tuples",
2005 kernel_config.size(), kernel_config.size()) << endl;
2006
2007
2008 kcf.close();
2009 return 0;
2010 }
2011
2012
2013 int
2014 systemtap_session::parse_kernel_exports ()
2015 {
2016 string kernel_exports_file = kernel_build_tree + "/Module.symvers";
2017 struct stat st;
2018 int rc = stat(kernel_exports_file.c_str(), &st);
2019 if (rc != 0)
2020 {
2021 clog << _F("Checking \"%s\" failed with error: %s\nEnsure kernel development headers & makefiles are installed",
2022 kernel_exports_file.c_str(), strerror(errno)) << endl;
2023 return rc;
2024 }
2025
2026 ifstream kef (kernel_exports_file.c_str());
2027 string line;
2028 while (getline (kef, line))
2029 {
2030 vector<string> tokens;
2031 tokenize (line, tokens, "\t");
2032 if (tokens.size() == 4 &&
2033 tokens[2] == "vmlinux" &&
2034 tokens[3].substr(0,13) == string("EXPORT_SYMBOL"))
2035 kernel_exports.insert (tokens[1]);
2036 // RHEL4 Module.symvers file only has 3 tokens. No
2037 // 'EXPORT_SYMBOL' token at the end of the line.
2038 else if (tokens.size() == 3 && tokens[2] == "vmlinux")
2039 kernel_exports.insert (tokens[1]);
2040 }
2041 if (verbose > 2)
2042 clog << _NF("Parsed kernel \"%s\", containing one vmlinux export",
2043 "Parsed kernel \"%s\", containing %zu vmlinux exports",
2044 kernel_exports.size(), kernel_exports_file.c_str(),
2045 kernel_exports.size()) << endl;
2046
2047 kef.close();
2048 return 0;
2049 }
2050
2051
2052 int
2053 systemtap_session::parse_kernel_functions ()
2054 {
2055 string system_map_path = kernel_build_tree + "/System.map";
2056 ifstream system_map;
2057
2058 system_map.open(system_map_path.c_str(), ifstream::in);
2059 if (! system_map.is_open())
2060 {
2061 if (verbose > 1)
2062 clog << _F("Kernel symbol table %s unavailable, (%s)",
2063 system_map_path.c_str(), strerror(errno)) << endl;
2064
2065 system_map_path = sysroot + "/boot/System.map-" + kernel_release;
2066 system_map.clear();
2067 system_map.open(system_map_path.c_str(), ifstream::in);
2068 if (! system_map.is_open())
2069 {
2070 if (verbose > 1)
2071 clog << _F("Kernel symbol table %s unavailable, (%s)",
2072 system_map_path.c_str(), strerror(errno)) << endl;
2073 }
2074 }
2075
2076 while (system_map.good())
2077 {
2078 assert_no_interrupts();
2079
2080 string address, type, name;
2081 system_map >> address >> type >> name;
2082
2083 if (verbose > 3)
2084 clog << "'" << address << "' '" << type << "' '" << name
2085 << "'" << endl;
2086
2087 // 'T'/'t' are text code symbols
2088 if (type != "t" && type != "T")
2089 continue;
2090
2091 #ifdef __powerpc__ // XXX cross-compiling hazard
2092 // Map ".sys_foo" to "sys_foo".
2093 if (name[0] == '.')
2094 name.erase(0, 1);
2095 #endif
2096
2097 // FIXME: better things to do here - look for _stext before
2098 // remembering symbols. Also:
2099 // - stop remembering names at ???
2100 // - what about __kprobes_text_start/__kprobes_text_end?
2101 kernel_functions.insert(name);
2102 }
2103 system_map.close();
2104
2105 if (kernel_functions.size() == 0)
2106 print_warning ("Kernel function symbol table missing [man warning::symbols]", 0);
2107
2108 if (verbose > 2)
2109 clog << _F("Parsed kernel \"%s\", ", system_map_path.c_str())
2110 << _NF("containing %zu symbol", "containing %zu symbols",
2111 kernel_functions.size(), kernel_functions.size()) << endl;
2112
2113 return 0;
2114 }
2115
2116
2117 string
2118 systemtap_session::cmd_file ()
2119 {
2120 wordexp_t words;
2121 string file;
2122
2123 if (target_pid && cmd == "")
2124 {
2125 // check that the target_pid corresponds to a running process
2126 string err_msg;
2127 if(!is_valid_pid (target_pid, err_msg))
2128 throw SEMANTIC_ERROR(err_msg);
2129
2130 file = string("/proc/") + lex_cast(target_pid) + "/exe";
2131 }
2132 else // default is to assume -c flag was given
2133 {
2134 int rc = wordexp (cmd.c_str (), &words, WRDE_NOCMD|WRDE_UNDEF);
2135 if(rc == 0)
2136 {
2137 if (words.we_wordc > 0)
2138 file = words.we_wordv[0];
2139 wordfree (& words);
2140 }
2141 else
2142 {
2143 switch (rc)
2144 {
2145 case WRDE_BADCHAR:
2146 throw SEMANTIC_ERROR(_("command contains illegal characters"));
2147 case WRDE_BADVAL:
2148 throw SEMANTIC_ERROR(_("command contains undefined shell variables"));
2149 case WRDE_CMDSUB:
2150 throw SEMANTIC_ERROR(_("command contains command substitutions"));
2151 case WRDE_NOSPACE:
2152 throw SEMANTIC_ERROR(_("out of memory"));
2153 case WRDE_SYNTAX:
2154 throw SEMANTIC_ERROR(_("command contains shell syntax errors"));
2155 default:
2156 throw SEMANTIC_ERROR(_("unspecified wordexp failure"));
2157 }
2158 }
2159 }
2160 return file;
2161 }
2162
2163
2164 void
2165 systemtap_session::init_try_server ()
2166 {
2167 #if HAVE_NSS
2168 // If the option is disabled or we are a server or we are already using a
2169 // server, then never retry compilation using a server.
2170 if (! use_server_on_error || client_options || ! specified_servers.empty ())
2171 try_server_status = dont_try_server;
2172 else
2173 try_server_status = try_server_unset;
2174 #else
2175 // No client, so don't bother.
2176 try_server_status = dont_try_server;
2177 #endif
2178 }
2179
2180 void
2181 systemtap_session::set_try_server (int t)
2182 {
2183 if (try_server_status != dont_try_server)
2184 try_server_status = t;
2185 }
2186
2187
2188 void systemtap_session::insert_loaded_modules()
2189 {
2190 char line[1024];
2191 ifstream procmods ("/proc/modules");
2192 while (procmods.good()) {
2193 procmods.getline (line, sizeof(line));
2194 strtok(line, " \t");
2195 if (line[0] == '\0')
2196 break; // maybe print a warning?
2197 unwindsym_modules.insert (string (line));
2198 }
2199 procmods.close();
2200 unwindsym_modules.insert ("kernel");
2201 }
2202
2203 void
2204 systemtap_session::setup_kernel_release (const string& kstr)
2205 {
2206 // Sometimes we may get dupes here... e.g. a server may have a full
2207 // -r /path/to/kernel followed by a client's -r kernel.
2208 if (kernel_release == kstr)
2209 return; // nothing new here...
2210
2211 kernel_release = kernel_build_tree = kernel_source_tree = "";
2212 if (kstr[0] == '/') // fully specified path
2213 {
2214 kernel_build_tree = kstr;
2215 kernel_release = kernel_release_from_build_tree (kernel_build_tree, verbose);
2216
2217 // PR10745
2218 // Maybe it's a full kernel source tree, for purposes of PR10745.
2219 // In case CONFIG_DEBUG_INFO was set, we'd find it anyway with the
2220 // normal search in tapsets.cxx. Without CONFIG_DEBUG_INFO, we'd
2221 // need heuristics such as this one:
2222
2223 string some_random_source_only_file = kernel_build_tree + "/COPYING";
2224 ifstream epic (some_random_source_only_file.c_str());
2225 if (! epic.fail())
2226 {
2227 kernel_source_tree = kernel_build_tree;
2228 if (verbose > 2)
2229 clog << _F("Located kernel source tree (COPYING) at '%s'", kernel_source_tree.c_str()) << endl;
2230 }
2231 }
2232 else
2233 {
2234 update_release_sysroot = true;
2235 kernel_release = kstr;
2236 if (!kernel_release.empty())
2237 kernel_build_tree = "/lib/modules/" + kernel_release + "/build";
2238
2239 // PR10745
2240 // Let's not look for the kernel_source_tree; it's definitely
2241 // not THERE. tapsets.cxx might try to find it later if tracepoints
2242 // need it.
2243 }
2244 }
2245
2246
2247 // Register all the aliases we've seen in library files, and the user
2248 // file, as patterns.
2249 void
2250 systemtap_session::register_library_aliases()
2251 {
2252 vector<stapfile*> files(library_files);
2253 files.insert(files.end(), user_files.begin(), user_files.end());
2254
2255 for (unsigned f = 0; f < files.size(); ++f)
2256 {
2257 stapfile * file = files[f];
2258 for (unsigned a = 0; a < file->aliases.size(); ++a)
2259 {
2260 probe_alias * alias = file->aliases[a];
2261 try
2262 {
2263 for (unsigned n = 0; n < alias->alias_names.size(); ++n)
2264 {
2265 probe_point * name = alias->alias_names[n];
2266 match_node * mn = pattern_root;
2267 for (unsigned c = 0; c < name->components.size(); ++c)
2268 {
2269 probe_point::component * comp = name->components[c];
2270 // XXX: alias parameters
2271 if (comp->arg)
2272 throw SEMANTIC_ERROR(_F("alias component %s contains illegal parameter",
2273 comp->functor.to_string().c_str()));
2274 mn = mn->bind(comp->functor);
2275 }
2276 // PR 12916: All probe aliases are OK for all users. The actual
2277 // referenced probe points will be checked when the alias is resolved.
2278 mn->bind_privilege (pr_all);
2279 mn->bind(new alias_expansion_builder(alias));
2280 }
2281 }
2282 catch (const semantic_error& e)
2283 {
2284 semantic_error er(ERR_SRC, _("while registering probe alias"),
2285 alias->tok, NULL, &e);
2286 print_error (er);
2287 }
2288 }
2289 }
2290 }
2291
2292
2293 // Print this given token, but abbreviate it if the last one had the
2294 // same file name.
2295 void
2296 systemtap_session::print_token (ostream& o, const token* tok)
2297 {
2298 assert (tok);
2299
2300 if (last_token && last_token->location.file == tok->location.file)
2301 {
2302 stringstream tmpo;
2303 tmpo << *tok;
2304 string ts = tmpo.str();
2305 // search & replace the file name with nothing
2306 size_t idx = ts.find (tok->location.file->name);
2307 if (idx != string::npos) {
2308 ts.erase(idx, tok->location.file->name.size()); // remove path
2309 if (color_errors) {
2310 string src = ts.substr(idx); // keep line & col
2311 ts.erase(idx); // remove from output string
2312 ts += colorize(src, "source"); // re-add it colorized
2313 }
2314 }
2315
2316 o << ts;
2317 }
2318 else
2319 o << colorize(tok);
2320
2321 last_token = tok;
2322 }
2323
2324
2325 void
2326 systemtap_session::print_error (const semantic_error& se)
2327 {
2328 // skip error message printing for listing mode with low verbosity
2329 if (this->dump_mode && this->verbose <= 1)
2330 {
2331 seen_errors[se.errsrc_chain()]++; // increment num_errors()
2332 return;
2333 }
2334
2335 // duplicate elimination
2336 if (verbose > 0 || seen_errors[se.errsrc_chain()] < 1)
2337 {
2338 seen_errors[se.errsrc_chain()]++;
2339 for (const semantic_error *e = &se; e != NULL; e = e->get_chain())
2340 cerr << build_error_msg(*e);
2341 }
2342 else suppressed_errors++;
2343 }
2344
2345 string
2346 systemtap_session::build_error_msg (const semantic_error& e)
2347 {
2348 stringstream message;
2349 string align_semantic_error (" ");
2350
2351 message << colorize(_("semantic error:"), "error") << ' ' << e.what ();
2352 if (e.tok1 || e.tok2)
2353 message << ": ";
2354 else
2355 {
2356 print_error_details (message, align_semantic_error, e);
2357 message << endl;
2358 if (verbose > 1) // no tokens to print, so print any errsrc right there
2359 message << _(" thrown from: ") << e.errsrc;
2360 }
2361
2362 if (e.tok1)
2363 {
2364 print_token (message, e.tok1);
2365 print_error_details (message, align_semantic_error, e);
2366 message << endl;
2367 if (verbose > 1)
2368 message << _(" thrown from: ") << e.errsrc << endl;
2369 print_error_source (message, align_semantic_error, e.tok1);
2370 }
2371 if (e.tok2)
2372 {
2373 print_token (message, e.tok2);
2374 message << endl;
2375 print_error_source (message, align_semantic_error, e.tok2);
2376 }
2377 message << endl;
2378 return message.str();
2379 }
2380
2381 void
2382 systemtap_session::print_error_source (std::ostream& message,
2383 std::string& align, const token* tok)
2384 {
2385 unsigned i = 0;
2386
2387 assert (tok);
2388 if (!tok->location.file)
2389 //No source to print, silently exit
2390 return;
2391
2392 unsigned line = tok->location.line;
2393 unsigned col = tok->location.column;
2394 interned_string file_contents = tok->location.file->file_contents;
2395
2396 size_t start_pos = 0, end_pos = 0;
2397 //Navigate to the appropriate line
2398 while (i != line && end_pos != std::string::npos)
2399 {
2400 start_pos = end_pos;
2401 end_pos = file_contents.find ('\n', start_pos) + 1;
2402 i++;
2403 }
2404 //TRANSLATORS: Here we are printing the source string of the error
2405 message << align << _("source: ");
2406 interned_string srcline = file_contents.substr(start_pos, end_pos-start_pos-1);
2407 if (color_errors) {
2408 // before token:
2409 message << srcline.substr(0, col-1);
2410 // token:
2411 // after token:
2412 // ... hold it - the token might have been synthetic,
2413 // or expanded from a $@ command line argument, or ...
2414 // so tok->content may have nothing in common with the
2415 // contents of srcline at the same point.
2416 interned_string srcline_rest = srcline.substr(col-1);
2417 interned_string srcline_tokenish = srcline_rest.substr(0, tok->content.size());
2418 if (srcline_tokenish == tok->content) { // oh good
2419 message << colorize(tok->content, "token");
2420 message << srcline_rest.substr(tok->content.size());
2421 message << endl;
2422 }
2423 else { // oh bad
2424 message << " ... ";
2425 col += 5; // line up with the caret
2426 message << colorize(tok->content, "token");
2427 message << " ... " << srcline_rest;
2428 message << endl;
2429 }
2430 } else
2431 message << srcline << endl;
2432 message << align << " ";
2433 //Navigate to the appropriate column
2434 for (i=start_pos; i<start_pos+col-1; i++)
2435 {
2436 if(isspace(file_contents[i]))
2437 message << file_contents[i];
2438 else
2439 message << ' ';
2440 }
2441 message << colorize("^", "caret") << endl;
2442
2443 // print chained macro invocations and synthesized code
2444 if (tok->chain)
2445 {
2446 if (tok->location.file->synthetic)
2447 message << _("\tin synthesized code from: ");
2448 else
2449 message << _("\tin expansion of macro: ");
2450 message << colorize(tok->chain) << endl;
2451 print_error_source (message, align, tok->chain);
2452 }
2453 }
2454
2455 void
2456 systemtap_session::print_error_details (std::ostream& message,
2457 std::string& align,
2458 const semantic_error& e)
2459 {
2460 for (size_t i = 0; i < e.details.size(); ++i)
2461 message << endl << align << e.details[i];
2462 }
2463
2464 void
2465 systemtap_session::print_warning (const string& message_str, const token* tok)
2466 {
2467 // Only output in dump mode if -vv is supplied:
2468 if (suppress_warnings && (!dump_mode || verbose <= 1))
2469 return; // NB: don't count towards suppressed_warnings count
2470
2471 // Duplicate elimination
2472 string align_warning (" ");
2473 if (verbose > 0 || seen_warnings.find (message_str) == seen_warnings.end())
2474 {
2475 seen_warnings.insert (message_str);
2476 clog << colorize(_("WARNING:"), "warning") << ' ' << message_str;
2477 if (tok) { clog << ": "; print_token (clog, tok); }
2478 clog << endl;
2479 if (tok) { print_error_source (clog, align_warning, tok); }
2480 }
2481 else suppressed_warnings++;
2482 }
2483
2484
2485 void
2486 systemtap_session::print_error (const parse_error &pe,
2487 const token* tok,
2488 const std::string &input_name,
2489 bool is_warningerr)
2490 {
2491 // duplicate elimination
2492 if (verbose > 0 || seen_errors[pe.errsrc_chain()] < 1)
2493 {
2494 // Sometimes, we need to print parse errors that should not be considered
2495 // critical. For example, when we parse tapsets and macros. In those
2496 // cases, is_warningerr is true, and we cancel out the increase in
2497 // seen_errors.size() by also increasing warningerr_count, so that the
2498 // net num_errors() value is unchanged.
2499 seen_errors[pe.errsrc_chain()]++; // can be simplified if we
2500 if (seen_errors[pe.errsrc_chain()] == 1 && is_warningerr) // change map to a set (and
2501 warningerr_count++; // settle on threshold of 1)
2502 cerr << build_error_msg(pe, tok, input_name);
2503 for (const parse_error *e = pe.chain; e != NULL; e = e->chain)
2504 cerr << build_error_msg(*e, e->tok, input_name);
2505 }
2506 else suppressed_errors++;
2507 }
2508
2509 string
2510 systemtap_session::build_error_msg (const parse_error& pe,
2511 const token* tok,
2512 const std::string &input_name)
2513 {
2514 stringstream message;
2515 string align_parse_error (" ");
2516
2517 // print either pe.what() or a deferred error from the lexer
2518 bool found_junk = false;
2519 if (tok && tok->type == tok_junk && tok->junk_type != tok_junk_unknown)
2520 {
2521 found_junk = true;
2522 message << colorize(_("parse error:"), "error") << ' '
2523 << tok->junk_message(*this) << endl;
2524 }
2525 else
2526 {
2527 message << colorize(_("parse error:"), "error") << ' ' << pe.what() << endl;
2528 }
2529
2530 // NB: It makes sense for lexer errors to always override parser
2531 // errors, since the original obvious scheme was for the lexer to
2532 // throw an exception before the token reached the parser.
2533
2534 if (pe.tok || found_junk)
2535 {
2536 message << align_parse_error << _(" at: ") << colorize(tok) << endl;
2537 print_error_source (message, align_parse_error, tok);
2538 }
2539 else if (tok) // "expected" type error
2540 {
2541 message << align_parse_error << _(" saw: ") << colorize(tok) << endl;
2542 print_error_source (message, align_parse_error, tok);
2543 }
2544 else
2545 {
2546 message << align_parse_error << _(" saw: ") << input_name << " EOF" << endl;
2547 }
2548 message << endl;
2549
2550 return message.str();
2551 }
2552
2553 void
2554 systemtap_session::report_suppression()
2555 {
2556 if (this->suppressed_errors > 0)
2557 cerr << colorize(_F("Number of similar error messages suppressed: %d.",
2558 this->suppressed_errors),
2559 "error") << endl;
2560 if (this->suppressed_warnings > 0)
2561 cerr << colorize(_F("Number of similar warning messages suppressed: %d.",
2562 this->suppressed_warnings),
2563 "warning") << endl;
2564 if (this->suppressed_errors > 0 || this->suppressed_warnings > 0)
2565 cerr << "Rerun with -v to see them." << endl;
2566 }
2567
2568 void
2569 systemtap_session::create_tmp_dir()
2570 {
2571 if (!tmpdir.empty())
2572 return;
2573
2574 if (tmpdir_opt_set)
2575 return;
2576
2577 // Create the temp directory
2578 const char * tmpdir_env = getenv("TMPDIR");
2579 if (!tmpdir_env)
2580 tmpdir_env = "/tmp";
2581
2582 string stapdir = "/stapXXXXXX";
2583 string tmpdirt = tmpdir_env + stapdir;
2584 const char *tmpdir_name = mkdtemp((char *)tmpdirt.c_str());
2585 if (! tmpdir_name)
2586 {
2587 const char* e = strerror(errno);
2588 //TRANSLATORS: we can't make the directory due to the error
2589 throw runtime_error(_F("cannot create temporary directory (\" %s \"): %s", tmpdirt.c_str(), e));
2590 }
2591 else
2592 tmpdir = tmpdir_name;
2593 }
2594
2595 void
2596 systemtap_session::remove_tmp_dir()
2597 {
2598 if(tmpdir.empty())
2599 return;
2600
2601 // Remove temporary directory
2602 if (keep_tmpdir && !tmpdir_opt_set)
2603 clog << _F("Keeping temporary directory \"%s\"", tmpdir.c_str()) << endl;
2604 else if (!tmpdir_opt_set)
2605 {
2606 // Mask signals while we're deleting the temporary directory.
2607 stap_sigmasker masked;
2608
2609 // Remove the temporary directory.
2610 vector<string> cleanupcmd { "rm", "-rf", tmpdir };
2611 (void) stap_system(verbose, cleanupcmd);
2612 if (verbose>1)
2613 clog << _F("Removed temporary directory \"%s\"", tmpdir.c_str()) << endl;
2614 tmpdir.clear();
2615
2616 }
2617 }
2618
2619 void
2620 systemtap_session::reset_tmp_dir()
2621 {
2622 remove_tmp_dir();
2623 create_tmp_dir();
2624 }
2625
2626 translator_output* systemtap_session::op_create_auxiliary(bool trailer_p)
2627 {
2628 static int counter = 0;
2629 string tmpname = this->tmpdir + "/" + this->module_name + "_aux_" + lex_cast(counter++) + ".c";
2630 translator_output* n = new translator_output (tmpname);
2631 n->trailer_p = trailer_p;
2632 auxiliary_outputs.push_back (n);
2633 return n;
2634 }
2635
2636 // Wrapper for checking if there are pending interrupts
2637 void
2638 assert_no_interrupts()
2639 {
2640 if (pending_interrupts)
2641 throw interrupt_exception();
2642 }
2643
2644 std::string
2645 systemtap_session::colorize(const std::string& str, const std::string& type)
2646 {
2647 if (str.empty() || !color_errors)
2648 return str;
2649 else {
2650 // Check if this type is defined in SYSTEMTAP_COLORS
2651 std::string color = parse_stap_color(type);
2652 if (!color.empty()) // no need to pollute terminal if not necessary
2653 return "\033[" + color + "m\033[K" + str + "\033[m\033[K";
2654 else
2655 return str;
2656 }
2657 }
2658
2659 // Colorizes the path:row:col part of the token
2660 std::string
2661 systemtap_session::colorize(const token* tok)
2662 {
2663 if (tok == NULL)
2664 return "";
2665
2666 stringstream tmp;
2667 tmp << *tok;
2668
2669 if (!color_errors)
2670 return tmp.str(); // Might as well stop now to save time
2671 else {
2672 string ts = tmp.str();
2673
2674 // Print token location, which is also the tail of ts
2675 stringstream loc;
2676 loc << tok->location;
2677
2678 // Remove token location and re-add it colorized
2679 ts.erase(ts.size()-loc.str().size());
2680 return ts + colorize(loc.str(), "source");
2681 }
2682 }
2683
2684 /* Parse SYSTEMTAP_COLORS and returns the SGR parameter(s) for the given
2685 type. The env var SYSTEMTAP_COLORS must be in the following format:
2686 'key1=val1:key2=val2:' etc... where valid keys are 'error', 'warning',
2687 'source', 'caret', 'token' and valid values constitute SGR parameter(s).
2688 For example, the default setting would be:
2689 'error=01;31:warning=00;33:source=00;34:caret=01:token=01'
2690 */
2691 std::string
2692 systemtap_session::parse_stap_color(const std::string& type)
2693 {
2694 const char *key, *col, *eq;
2695 int n = type.size();
2696 int done = 0;
2697
2698 key = getenv("SYSTEMTAP_COLORS");
2699 if (key == NULL)
2700 key = "error=01;31:warning=00;33:source=00;34:caret=01:token=01";
2701 else if (*key == '\0')
2702 return ""; // disable colors if set but empty
2703
2704 while (!done) {
2705 if (!(col = strchr(key, ':'))) {
2706 col = strchr(key, '\0');
2707 done = 1;
2708 }
2709 if (!((eq = strchr(key, '=')) && eq < col))
2710 return ""; /* invalid syntax: no = in range */
2711 if (!(key < eq && eq < col-1))
2712 return ""; /* invalid syntax: key or val empty */
2713 if (strspn(eq+1, "0123456789;") < (size_t)(col-eq-1))
2714 return ""; /* invalid syntax: invalid char in val */
2715 if (eq-key == n && type.compare(0, n, key, n) == 0)
2716 return string(eq+1, col-eq-1);
2717 if (!done) key = col+1; /* advance to next key */
2718 }
2719
2720 // Could not find the key
2721 return "";
2722 }
2723
2724 /*
2725 * Returns true if this system requires modules to have signatures
2726 * (typically on a secure boot system), false otherwise.
2727 *
2728 * This routine parses /sys/module/module/parameters/sig_enforce to
2729 * figure out if signatures are enforced on modules. Note that if the
2730 * file doesn't exist, we don't really care and return false.
2731 *
2732 * On certain kernels (RHEL7), we also have to check
2733 * /sys/kernel/security/securelevel.
2734 */
2735 bool
2736 systemtap_session::modules_must_be_signed()
2737 {
2738 ifstream statm("/sys/module/module/parameters/sig_enforce");
2739 ifstream securelevel("/sys/kernel/security/securelevel");
2740 char status = 'N';
2741
2742 statm >> status;
2743 if (status == 'Y')
2744 return true;
2745
2746 securelevel >> status;
2747 if (status == '1')
2748 return true;
2749 return false;
2750 }
2751
2752 /*
2753 * Get information on the list of enrolled machine owner keys (MOKs) on
2754 * this system.
2755 */
2756 void
2757 systemtap_session::get_mok_info()
2758 {
2759 int rc;
2760 stringstream out;
2761
2762 // FIXME: In theory, we should be able to read /sys files and use
2763 // some of the guts of read_cert_info_from_file() to get the
2764 // fingerprints. This would rid us of our mokutil
2765 // dependency. However, we'd need to copy/duplicate efilib.c from
2766 // mokutil source to be able to decipher the efi data.
2767
2768 vector<string> cmd { "mokutil", "--list-enrolled" };
2769 rc = stap_system_read(verbose, cmd, out);
2770 if (rc != 0)
2771 // If we're here, we know the client requires module signing, but
2772 // we can't get the list of MOKs. Quit.
2773 throw runtime_error(_F("failed to get list of machine owner keys (MOK) fingerprints: rc %d", rc));
2774
2775 string line, fingerprint;
2776 while (! out.eof())
2777 {
2778 vector<string> matches;
2779
2780 // Get a line of the output, then try to find the fingerprint in
2781 // the line.
2782 getline(out, line);
2783 if (! regexp_match(line, "^SHA1 Fingerprint: ([0-9a-f:]+)$", matches))
2784 {
2785 // matches[0] is the entire line, matches[1] is the first
2786 // submatch, in this case the actual fingerprint
2787 if (verbose > 2)
2788 clog << "MOK fingerprint found: " << matches[1] << endl;
2789 if (! matches[1].empty())
2790 mok_fingerprints.push_back(matches[1]);
2791 }
2792 }
2793 }
2794
2795 void
2796 systemtap_session::enable_auto_server (const string &message)
2797 {
2798 // There may be more than one reason to enable auto server mode, so we may be called
2799 // more than once. Accumulate the messages.
2800 auto_server_msgs.push_back (message);
2801
2802 #if HAVE_NSS
2803 // Enable auto server mode, if not enabled already.
2804 if (specified_servers.empty())
2805 specified_servers.push_back ("");
2806 #else
2807 // Compilation using a server is not supported. exit() after
2808 // the first explanation.
2809 explain_auto_options ();
2810 clog << _("Unable to request compilation by a compile-server\n."
2811 "Without NSS, --use-server is not supported by this version systemtap.") << endl;
2812 exit(1);
2813 #endif
2814 }
2815
2816 void
2817 systemtap_session::explain_auto_options()
2818 {
2819 // Was there an automatic privilege setting?
2820 if (! auto_privilege_level_msg.empty())
2821 clog << auto_privilege_level_msg << endl;
2822
2823 // Was a server was automatically requested? Handle this one after other auto_settings
2824 // which may result in an auto_server setting.
2825 if (! auto_server_msgs.empty())
2826 {
2827 for (vector<string>::iterator i = auto_server_msgs.begin(); i != auto_server_msgs.end(); ++i)
2828 {
2829 clog << *i << endl;
2830 clog << _("--use-server was automatically selected in order to request compilation by "
2831 "a compile-server.") << endl;
2832 }
2833 }
2834 }
2835
2836 bool
2837 systemtap_session::is_user_file (const string &name)
2838 {
2839 // base the check on the name of the user_file
2840 for (vector<stapfile*>::iterator it = user_files.begin(); it != user_files.end(); it++)
2841 if (name == (*it)->name)
2842 return true;
2843 return false; // no match
2844 }
2845
2846 bool
2847 systemtap_session::is_primary_probe (derived_probe *dp)
2848 {
2849 // We check if this probe is from the primary user file by going back to its
2850 // original probe and checking if that probe was found in the primary user
2851 // file.
2852
2853 if (user_files.empty())
2854 return false;
2855
2856 vector<probe*> chain;
2857 dp->collect_derivation_chain (chain);
2858 const source_loc& origin = chain.back()->tok->location;
2859 return origin.file == user_files[0];
2860 }
2861
2862 void
2863 systemtap_session::clear_script_data()
2864 {
2865 delete pattern_root;
2866 pattern_root = new match_node;
2867
2868 // We need to be sure to reset all our error counts, so that an
2869 // error on one script won't be counted against the next script.
2870 seen_warnings.clear();
2871 suppressed_warnings = 0;
2872 seen_errors.clear();
2873 suppressed_errors = 0;
2874 warningerr_count = 0;
2875 }
2876
2877 // --------------------------------------------------------------------------
2878
2879 /*
2880 Perngrq sebz fzvyrlgnc.fit, rkcbegrq gb n 1484k1110 fzvyrlgnc.cat,
2881 gurapr catgbcnz | cazfpnyr -jvqgu 160 |
2882 cczqvgure -qvz 4 -erq 2 -terra 2 -oyhr 2 | cczgbnafv -2k4 | bq -i -j19 -g k1 |
2883 phg -s2- -q' ' | frq -r 'f,^,\\k,' -r 'f, ,\\k,t' -r 'f,^,",' -r 'f,$,",'
2884 */
2885 const char*
2886 systemtap_session::morehelp =
2887 "\x1b\x5b\x30\x6d\x1b\x5b\x33\x37\x6d\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20"
2888 "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20"
2889 "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20"
2890 "\x20\x20\x20\x60\x20\x20\x2e\x60\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20"
2891 "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x20"
2892 "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20"
2893 "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20"
2894 "\x20\x20\x60\x20\x60\x20\x60\x20\x60\x20\x60\x20\x60\x20\x60\x20\x60\x1b\x5b"
2895 "\x33\x33\x6d\x20\x1b\x5b\x33\x37\x6d\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20"
2896 "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20"
2897 "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20"
2898 "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x1b\x5b\x33\x33\x6d\x20\x60"
2899 "\x2e\x60\x1b\x5b\x33\x37\x6d\x20\x3a\x2c\x3a\x2e\x60\x20\x60\x20\x60\x20\x60"
2900 "\x2c\x3b\x2c\x3a\x20\x1b\x5b\x33\x33\x6d\x60\x2e\x60\x20\x1b\x5b\x33\x37\x6d"
2901 "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x0a\x20\x20\x20"
2902 "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20"
2903 "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x1b\x5b\x33"
2904 "\x33\x6d\x20\x60\x20\x60\x20\x3a\x27\x60\x1b\x5b\x33\x37\x6d\x20\x60\x60\x60"
2905 "\x20\x20\x20\x60\x20\x60\x60\x60\x20\x1b\x5b\x33\x33\x6d\x60\x3a\x60\x20\x60"
2906 "\x20\x60\x20\x1b\x5b\x33\x37\x6d\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20"
2907 "\x20\x20\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20"
2908 "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20"
2909 "\x20\x2e\x1b\x5b\x33\x33\x6d\x60\x2e\x60\x20\x60\x20\x60\x20\x20\x1b\x5b\x33"
2910 "\x37\x6d\x20\x3a\x20\x20\x20\x60\x20\x20\x20\x60\x20\x20\x2e\x1b\x5b\x33\x33"
2911 "\x6d\x60\x20\x60\x2e\x60\x20\x60\x2e\x60\x20\x1b\x5b\x33\x37\x6d\x20\x20\x20"
2912 "\x20\x20\x20\x20\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x20\x20\x2e\x3a\x20\x20"
2913 "\x20\x20\x20\x20\x20\x20\x2e\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20"
2914 "\x20\x20\x2e\x76\x53\x1b\x5b\x33\x34\x6d\x53\x1b\x5b\x33\x37\x6d\x53\x1b\x5b"
2915 "\x33\x31\x6d\x2b\x1b\x5b\x33\x33\x6d\x60\x20\x60\x20\x60\x20\x20\x20\x20\x1b"
2916 "\x5b\x33\x31\x6d\x3f\x1b\x5b\x33\x30\x6d\x53\x1b\x5b\x33\x33\x6d\x2b\x1b\x5b"
2917 "\x33\x37\x6d\x20\x20\x20\x20\x20\x20\x20\x2e\x1b\x5b\x33\x30\x6d\x24\x1b\x5b"
2918 "\x33\x37\x6d\x3b\x1b\x5b\x33\x31\x6d\x7c\x1b\x5b\x33\x33\x6d\x20\x60\x20\x60"
2919 "\x20\x60\x20\x60\x1b\x5b\x33\x31\x6d\x2c\x1b\x5b\x33\x32\x6d\x53\x1b\x5b\x33"
2920 "\x37\x6d\x53\x53\x3e\x2c\x2e\x20\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x20\x2e"
2921 "\x3b\x27\x20\x20\x20\x20\x20\x20\x20\x20\x20\x60\x3c\x20\x20\x20\x20\x20\x20"
2922 "\x20\x20\x20\x2e\x2e\x3a\x1b\x5b\x33\x30\x6d\x26\x46\x46\x46\x48\x46\x1b\x5b"
2923 "\x33\x33\x6d\x60\x2e\x60\x20\x60\x20\x60\x20\x60\x1b\x5b\x33\x30\x6d\x4d\x4d"
2924 "\x46\x1b\x5b\x33\x33\x6d\x20\x20\x1b\x5b\x33\x37\x6d\x20\x20\x20\x20\x1b\x5b"
2925 "\x33\x33\x6d\x20\x3a\x1b\x5b\x33\x30\x6d\x4d\x4d\x46\x1b\x5b\x33\x33\x6d\x20"
2926 "\x20\x20\x60\x20\x60\x2e\x60\x1b\x5b\x33\x31\x6d\x3c\x1b\x5b\x33\x30\x6d\x46"
2927 "\x46\x46\x24\x53\x46\x1b\x5b\x33\x37\x6d\x20\x20\x20\x20\x20\x0a\x20\x20\x20"
2928 "\x20\x2e\x3c\x3a\x60\x20\x20\x20\x20\x2e\x3a\x2e\x3a\x2e\x2e\x3b\x27\x20\x20"
2929 "\x20\x20\x20\x20\x2e\x60\x2e\x3a\x60\x60\x3c\x27\x1b\x5b\x33\x31\x6d\x3c\x27"
2930 "\x1b\x5b\x33\x33\x6d\x20\x60\x20\x60\x20\x60\x20\x20\x20\x60\x3c\x1b\x5b\x33"
2931 "\x30\x6d\x26\x1b\x5b\x33\x31\x6d\x3f\x1b\x5b\x33\x33\x6d\x20\x1b\x5b\x33\x37"
2932 "\x6d\x20\x1b\x5b\x33\x33\x6d\x20\x20\x20\x20\x20\x1b\x5b\x33\x37\x6d\x60\x1b"
2933 "\x5b\x33\x30\x6d\x2a\x46\x1b\x5b\x33\x37\x6d\x27\x1b\x5b\x33\x33\x6d\x20\x60"
2934 "\x20\x60\x20\x60\x20\x60\x20\x1b\x5b\x33\x31\x6d\x60\x3a\x1b\x5b\x33\x37\x6d"
2935 "\x27\x3c\x1b\x5b\x33\x30\x6d\x23\x1b\x5b\x33\x37\x6d\x3c\x60\x3a\x20\x20\x20"
2936 "\x0a\x20\x20\x20\x20\x3a\x60\x3a\x60\x20\x20\x20\x60\x3a\x2e\x2e\x2e\x2e\x3c"
2937 "\x3c\x20\x20\x20\x20\x20\x20\x3a\x2e\x60\x3a\x60\x20\x20\x20\x60\x1b\x5b\x33"
2938 "\x33\x6d\x3a\x1b\x5b\x33\x31\x6d\x60\x1b\x5b\x33\x33\x6d\x20\x60\x2e\x60\x20"
2939 "\x60\x20\x60\x20\x60\x20\x60\x1b\x5b\x33\x37\x6d\x20\x20\x1b\x5b\x33\x33\x6d"
2940 "\x20\x60\x20\x20\x20\x60\x1b\x5b\x33\x37\x6d\x20\x60\x20\x60\x1b\x5b\x33\x33"
2941 "\x6d\x20\x60\x2e\x60\x20\x60\x2e\x60\x20\x60\x3a\x1b\x5b\x33\x37\x6d\x20\x20"
2942 "\x20\x60\x3a\x2e\x60\x2e\x20\x0a\x20\x20\x20\x60\x3a\x60\x3a\x60\x20\x20\x20"
2943 "\x20\x20\x60\x60\x60\x60\x20\x3a\x2d\x20\x20\x20\x20\x20\x60\x20\x60\x20\x20"
2944 "\x20\x20\x20\x60\x1b\x5b\x33\x33\x6d\x3a\x60\x2e\x60\x20\x60\x20\x60\x20\x60"
2945 "\x20\x60\x20\x20\x2e\x3b\x1b\x5b\x33\x31\x6d\x76\x1b\x5b\x33\x30\x6d\x24\x24"
2946 "\x24\x1b\x5b\x33\x31\x6d\x2b\x53\x1b\x5b\x33\x33\x6d\x2c\x60\x20\x60\x20\x60"
2947 "\x20\x60\x20\x60\x20\x60\x2e\x1b\x5b\x33\x31\x6d\x60\x1b\x5b\x33\x33\x6d\x3a"
2948 "\x1b\x5b\x33\x37\x6d\x20\x20\x20\x20\x60\x2e\x60\x20\x20\x0a\x20\x20\x20\x60"
2949 "\x3a\x3a\x3a\x3a\x20\x20\x20\x20\x3a\x60\x60\x60\x60\x3a\x53\x20\x20\x20\x20"
2950 "\x20\x20\x3a\x2e\x60\x2e\x20\x20\x20\x20\x20\x1b\x5b\x33\x33\x6d\x3a\x1b\x5b"
2951 "\x33\x31\x6d\x3a\x1b\x5b\x33\x33\x6d\x2e\x60\x2e\x60\x20\x60\x2e\x60\x20\x60"
2952 "\x20\x3a\x1b\x5b\x33\x30\x6d\x24\x46\x46\x48\x46\x46\x46\x46\x46\x1b\x5b\x33"
2953 "\x31\x6d\x53\x1b\x5b\x33\x33\x6d\x2e\x60\x20\x60\x2e\x60\x20\x60\x2e\x60\x2e"
2954 "\x1b\x5b\x33\x31\x6d\x3a\x1b\x5b\x33\x33\x6d\x3a\x1b\x5b\x33\x37\x6d\x20\x20"
2955 "\x20\x2e\x60\x2e\x3a\x20\x20\x0a\x20\x20\x20\x60\x3a\x3a\x3a\x60\x20\x20\x20"
2956 "\x60\x3a\x20\x2e\x20\x3b\x27\x3a\x20\x20\x20\x20\x20\x20\x3a\x2e\x60\x3a\x20"
2957 "\x20\x20\x20\x20\x3a\x1b\x5b\x33\x33\x6d\x3c\x3a\x1b\x5b\x33\x31\x6d\x60\x1b"
2958 "\x5b\x33\x33\x6d\x2e\x60\x20\x60\x20\x60\x20\x60\x2e\x1b\x5b\x33\x30\x6d\x53"
2959 "\x46\x46\x46\x53\x46\x46\x46\x53\x46\x46\x1b\x5b\x33\x33\x6d\x20\x60\x20\x60"
2960 "\x20\x60\x2e\x60\x2e\x60\x3a\x1b\x5b\x33\x31\x6d\x3c\x1b\x5b\x33\x37\x6d\x20"
2961 "\x20\x20\x20\x3a\x60\x3a\x60\x20\x20\x0a\x20\x20\x20\x20\x60\x3c\x3b\x3c\x20"
2962 "\x20\x20\x20\x20\x60\x60\x60\x20\x3a\x3a\x20\x20\x20\x20\x20\x20\x20\x3a\x3a"
2963 "\x2e\x60\x20\x20\x20\x20\x20\x3a\x1b\x5b\x33\x33\x6d\x3b\x1b\x5b\x33\x31\x6d"
2964 "\x3c\x3a\x60\x1b\x5b\x33\x33\x6d\x2e\x60\x2e\x60\x20\x60\x3a\x1b\x5b\x33\x30"
2965 "\x6d\x53\x46\x53\x46\x46\x46\x53\x46\x46\x46\x53\x1b\x5b\x33\x33\x6d\x2e\x60"
2966 "\x20\x60\x2e\x60\x2e\x60\x3a\x1b\x5b\x33\x31\x6d\x3c\x1b\x5b\x33\x33\x6d\x3b"
2967 "\x1b\x5b\x33\x37\x6d\x27\x20\x20\x20\x60\x3a\x3a\x60\x20\x20\x20\x0a\x20\x20"
2968 "\x20\x20\x20\x60\x3b\x3c\x20\x20\x20\x20\x20\x20\x20\x3a\x3b\x60\x20\x20\x20"
2969 "\x20\x20\x20\x20\x20\x20\x60\x3a\x60\x2e\x20\x20\x20\x20\x20\x3a\x1b\x5b\x33"
2970 "\x33\x6d\x3c\x3b\x1b\x5b\x33\x31\x6d\x3c\x1b\x5b\x33\x33\x6d\x3a\x1b\x5b\x33"
2971 "\x31\x6d\x3a\x1b\x5b\x33\x33\x6d\x2e\x60\x2e\x60\x20\x1b\x5b\x33\x31\x6d\x3a"
2972 "\x1b\x5b\x33\x30\x6d\x46\x53\x46\x53\x46\x53\x46\x53\x46\x1b\x5b\x33\x31\x6d"
2973 "\x3f\x1b\x5b\x33\x33\x6d\x20\x60\x2e\x60\x2e\x3a\x3a\x1b\x5b\x33\x31\x6d\x3c"
2974 "\x1b\x5b\x33\x33\x6d\x3b\x1b\x5b\x33\x31\x6d\x3c\x1b\x5b\x33\x37\x6d\x60\x20"
2975 "\x20\x20\x3a\x3a\x3a\x60\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x20\x20\x53\x3c"
2976 "\x20\x20\x20\x20\x20\x20\x3a\x53\x3a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20"
2977 "\x20\x60\x3a\x3a\x60\x2e\x20\x20\x20\x20\x60\x3a\x1b\x5b\x33\x31\x6d\x3c\x1b"
2978 "\x5b\x33\x33\x6d\x3b\x1b\x5b\x33\x31\x6d\x3c\x3b\x3c\x1b\x5b\x33\x33\x6d\x3a"
2979 "\x60\x2e\x60\x3c\x1b\x5b\x33\x30\x6d\x53\x46\x53\x24\x53\x46\x53\x24\x1b\x5b"
2980 "\x33\x33\x6d\x60\x3a\x1b\x5b\x33\x31\x6d\x3a\x1b\x5b\x33\x33\x6d\x3a\x1b\x5b"
2981 "\x33\x31\x6d\x3a\x3b\x3c\x1b\x5b\x33\x33\x6d\x3b\x1b\x5b\x33\x31\x6d\x3c\x1b"
2982 "\x5b\x33\x33\x6d\x3a\x1b\x5b\x33\x37\x6d\x60\x20\x20\x2e\x60\x3a\x3a\x60\x20"
2983 "\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x20\x20\x3b\x3c\x2e\x2e\x2c\x2e\x2e\x20"
2984 "\x3a\x3c\x3b\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x60\x3a\x3a\x3a"
2985 "\x60\x20\x20\x20\x20\x20\x60\x3a\x1b\x5b\x33\x33\x6d\x3c\x3b\x1b\x5b\x33\x31"
2986 "\x6d\x3c\x3b\x3c\x1b\x5b\x33\x33\x6d\x3b\x1b\x5b\x33\x31\x6d\x3c\x1b\x5b\x33"
2987 "\x33\x6d\x3b\x1b\x5b\x33\x31\x6d\x3c\x3c\x1b\x5b\x33\x30\x6d\x53\x24\x53\x1b"
2988 "\x5b\x33\x31\x6d\x53\x1b\x5b\x33\x37\x6d\x27\x1b\x5b\x33\x33\x6d\x2e\x3a\x3b"
2989 "\x1b\x5b\x33\x31\x6d\x3c\x3b\x3c\x1b\x5b\x33\x33\x6d\x3a\x1b\x5b\x33\x31\x6d"
2990 "\x3c\x1b\x5b\x33\x33\x6d\x3a\x1b\x5b\x33\x37\x6d\x60\x20\x20\x20\x60\x2e\x3a"
2991 "\x3a\x20\x20\x20\x20\x20\x20\x20\x0a\x20\x20\x2e\x3a\x3a\x3c\x53\x3c\x3a\x60"
2992 "\x3a\x3a\x3a\x3a\x53\x1b\x5b\x33\x32\x6d\x53\x1b\x5b\x33\x37\x6d\x3b\x27\x3a"
2993 "\x3c\x2c\x2e\x20\x20\x20\x20\x20\x20\x20\x20\x20\x60\x3a\x3a\x3a\x3a\x2e\x60"
2994 "\x2e\x60\x2e\x60\x3a\x1b\x5b\x33\x33\x6d\x3c\x3a\x1b\x5b\x33\x31\x6d\x3c\x1b"
2995 "\x5b\x33\x33\x6d\x53\x1b\x5b\x33\x31\x6d\x3c\x1b\x5b\x33\x33\x6d\x3b\x1b\x5b"
2996 "\x33\x31\x6d\x3c\x2c\x1b\x5b\x33\x33\x6d\x3c\x3b\x3a\x1b\x5b\x33\x31\x6d\x2c"
2997 "\x1b\x5b\x33\x33\x6d\x3c\x3b\x1b\x5b\x33\x31\x6d\x3c\x1b\x5b\x33\x33\x6d\x53"
2998 "\x1b\x5b\x33\x31\x6d\x3c\x1b\x5b\x33\x33\x6d\x3b\x3c\x1b\x5b\x33\x37\x6d\x3a"
2999 "\x60\x2e\x60\x2e\x3b\x1b\x5b\x33\x34\x6d\x53\x1b\x5b\x33\x37\x6d\x53\x3f\x27"
3000 "\x20\x20\x20\x20\x20\x20\x20\x20\x0a\x2e\x60\x3a\x60\x3a\x3c\x53\x53\x3b\x3c"
3001 "\x3a\x60\x3a\x3a\x53\x53\x53\x3c\x3a\x60\x3a\x1b\x5b\x33\x30\x6d\x53\x1b\x5b"
3002 "\x33\x37\x6d\x2b\x20\x20\x20\x20\x20\x20\x60\x20\x20\x20\x3a\x1b\x5b\x33\x34"
3003 "\x6d\x53\x1b\x5b\x33\x30\x6d\x53\x46\x24\x1b\x5b\x33\x37\x6d\x2c\x60\x3a\x3a"
3004 "\x3a\x3c\x3a\x3c\x1b\x5b\x33\x33\x6d\x53\x1b\x5b\x33\x37\x6d\x3c\x1b\x5b\x33"
3005 "\x33\x6d\x53\x1b\x5b\x33\x31\x6d\x53\x1b\x5b\x33\x33\x6d\x3b\x1b\x5b\x33\x31"
3006 "\x6d\x53\x3b\x53\x1b\x5b\x33\x33\x6d\x3b\x1b\x5b\x33\x31\x6d\x53\x1b\x5b\x33"
3007 "\x33\x6d\x53\x1b\x5b\x33\x37\x6d\x3c\x1b\x5b\x33\x33\x6d\x53\x1b\x5b\x33\x37"
3008 "\x6d\x3c\x53\x3c\x3a\x3a\x3a\x3a\x3f\x1b\x5b\x33\x30\x6d\x53\x24\x48\x1b\x5b"
3009 "\x33\x37\x6d\x27\x60\x20\x60\x20\x20\x20\x20\x20\x20\x0a\x2e\x60\x3a\x60\x2e"
3010 "\x60\x3a\x60\x2e\x60\x3a\x60\x2e\x60\x3a\x60\x2e\x60\x3a\x60\x2e\x1b\x5b\x33"
3011 "\x30\x6d\x53\x46\x1b\x5b\x33\x37\x6d\x20\x20\x20\x20\x60\x20\x20\x20\x60\x20"
3012 "\x60\x3a\x1b\x5b\x33\x30\x6d\x3c\x46\x46\x46\x1b\x5b\x33\x37\x6d\x3f\x2e\x60"
3013 "\x3a\x60\x3a\x60\x3a\x60\x3a\x60\x3a\x3c\x3a\x60\x3a\x27\x3a\x60\x3a\x60\x3a"
3014 "\x60\x3a\x60\x3b\x1b\x5b\x33\x30\x6d\x53\x46\x48\x46\x1b\x5b\x33\x37\x6d\x27"
3015 "\x20\x60\x20\x60\x20\x60\x20\x20\x20\x20\x0a\x20\x3c\x3b\x3a\x2e\x60\x20\x60"
3016 "\x2e\x60\x20\x60\x2e\x60\x20\x60\x2e\x60\x2c\x53\x1b\x5b\x33\x32\x6d\x53\x1b"
3017 "\x5b\x33\x30\x6d\x53\x1b\x5b\x33\x37\x6d\x20\x20\x20\x20\x20\x20\x20\x20\x20"
3018 "\x20\x20\x60\x20\x60\x3c\x1b\x5b\x33\x30\x6d\x46\x46\x46\x1b\x5b\x33\x34\x6d"
3019 "\x2b\x1b\x5b\x33\x37\x6d\x3a\x20\x60\x20\x60\x20\x60\x2e\x60\x20\x60\x2e\x60"
3020 "\x20\x60\x2e\x60\x20\x60\x20\x60\x2c\x1b\x5b\x33\x30\x6d\x24\x46\x48\x46\x1b"
3021 "\x5b\x33\x37\x6d\x27\x20\x60\x20\x20\x20\x60\x20\x20\x20\x20\x20\x20\x0a\x20"
3022 "\x60\x3a\x1b\x5b\x33\x30\x6d\x53\x24\x1b\x5b\x33\x37\x6d\x53\x53\x53\x3b\x3c"
3023 "\x2c\x60\x2c\x3b\x3b\x53\x3f\x53\x1b\x5b\x33\x30\x6d\x24\x46\x3c\x1b\x5b\x33"
3024 "\x37\x6d\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x60\x20\x60"
3025 "\x3c\x1b\x5b\x33\x30\x6d\x48\x46\x46\x46\x1b\x5b\x33\x37\x6d\x3f\x2e\x60\x20"
3026 "\x60\x20\x60\x20\x60\x20\x60\x20\x60\x20\x60\x20\x3b\x76\x1b\x5b\x33\x30\x6d"
3027 "\x48\x46\x48\x46\x1b\x5b\x33\x37\x6d\x27\x20\x60\x20\x20\x20\x60\x20\x20\x20"
3028 "\x20\x20\x20\x20\x20\x0a\x20\x20\x20\x60\x3c\x1b\x5b\x33\x30\x6d\x46\x24\x1b"
3029 "\x5b\x33\x37\x6d\x53\x53\x53\x53\x53\x53\x1b\x5b\x33\x30\x6d\x53\x24\x53\x46"
3030 "\x46\x46\x1b\x5b\x33\x37\x6d\x27\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20"
3031 "\x20\x20\x20\x20\x20\x20\x20\x20\x60\x3c\x1b\x5b\x33\x30\x6d\x23\x46\x46\x46"
3032 "\x24\x1b\x5b\x33\x37\x6d\x76\x2c\x2c\x20\x2e\x20\x2e\x20\x2c\x2c\x76\x1b\x5b"
3033 "\x33\x30\x6d\x26\x24\x46\x46\x48\x3c\x1b\x5b\x33\x37\x6d\x27\x20\x20\x20\x20"
3034 "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x20\x60"
3035 "\x3c\x1b\x5b\x33\x30\x6d\x53\x46\x46\x24\x46\x24\x46\x46\x48\x46\x53\x1b\x5b"
3036 "\x33\x37\x6d\x20\x20\x20\x20\x20\x20\x20\x20\x2e\x60\x20\x60\x2e\x60\x2e\x60"
3037 "\x2e\x60\x2e\x60\x3a\x3a\x3a\x3a\x3a\x1b\x5b\x33\x30\x6d\x2a\x46\x46\x46\x48"
3038 "\x46\x48\x46\x48\x46\x46\x46\x48\x46\x48\x46\x48\x1b\x5b\x33\x37\x6d\x3c\x22"
3039 "\x2e\x60\x2e\x60\x2e\x60\x2e\x60\x2e\x60\x20\x20\x20\x20\x20\x20\x20\x20\x0a"
3040 "\x20\x20\x20\x20\x20\x20\x20\x60\x3a\x1b\x5b\x33\x30\x6d\x48\x46\x46\x46\x48"
3041 "\x46\x46\x46\x1b\x5b\x33\x37\x6d\x27\x20\x20\x20\x60\x20\x60\x2e\x60\x20\x60"
3042 "\x2e\x60\x2e\x60\x3a\x60\x3a\x60\x3a\x60\x3a\x60\x3a\x3a\x3a\x60\x3a\x3c\x3c"
3043 "\x1b\x5b\x33\x30\x6d\x3c\x46\x48\x46\x46\x46\x48\x46\x46\x46\x1b\x5b\x33\x37"
3044 "\x6d\x27\x3a\x60\x3a\x60\x3a\x60\x3a\x60\x2e\x60\x2e\x60\x20\x60\x2e\x60\x20"
3045 "\x60\x20\x60\x20\x20\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x60\x22\x1b\x5b"
3046 "\x33\x30\x6d\x2a\x46\x48\x46\x1b\x5b\x33\x37\x6d\x3f\x20\x20\x20\x60\x20\x60"
3047 "\x2e\x60\x20\x60\x2e\x60\x2e\x60\x3a\x60\x2e\x60\x3a\x60\x3a\x60\x3a\x60\x3a"
3048 "\x60\x3a\x60\x3a\x60\x3a\x60\x3a\x1b\x5b\x33\x30\x6d\x46\x46\x48\x46\x48\x46"
3049 "\x1b\x5b\x33\x37\x6d\x27\x3a\x60\x3a\x60\x3a\x60\x3a\x60\x2e\x60\x3a\x60\x2e"
3050 "\x60\x2e\x60\x20\x60\x2e\x60\x20\x60\x20\x60\x0a\x20\x20\x20\x20\x20\x20\x20"
3051 "\x20\x20\x20\x20\x60\x3c\x1b\x5b\x33\x30\x6d\x48\x46\x46\x1b\x5b\x33\x37\x6d"
3052 "\x2b\x60\x20\x20\x20\x60\x20\x60\x20\x60\x20\x60\x20\x60\x20\x60\x2e\x60\x20"
3053 "\x60\x2e\x60\x20\x60\x2e\x60\x20\x60\x3a\x60\x2e\x60\x3b\x1b\x5b\x33\x30\x6d"
3054 "\x48\x46\x46\x46\x1b\x5b\x33\x37\x6d\x27\x2e\x60\x2e\x60\x20\x60\x2e\x60\x20"
3055 "\x60\x2e\x60\x20\x60\x20\x60\x20\x60\x20\x60\x20\x20\x20\x60\x20\x20\x0a\x20"
3056 "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x22\x1b\x5b\x33\x30\x6d\x3c"
3057 "\x48\x46\x53\x1b\x5b\x33\x37\x6d\x2b\x3a\x20\x20\x20\x60\x20\x60\x20\x60\x20"
3058 "\x60\x20\x60\x20\x60\x20\x60\x20\x60\x20\x60\x20\x60\x20\x60\x20\x60\x2c\x1b"
3059 "\x5b\x33\x30\x6d\x24\x46\x48\x46\x1b\x5b\x33\x37\x6d\x3f\x20\x60\x20\x60\x20"
3060 "\x60\x20\x60\x20\x60\x20\x60\x20\x60\x20\x60\x20\x60\x20\x60\x20\x20\x20\x60"
3061 "\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20"
3062 "\x60\x22\x3c\x1b\x5b\x33\x30\x6d\x48\x24\x46\x46\x1b\x5b\x33\x37\x6d\x3e\x2c"
3063 "\x2e\x2e\x20\x20\x20\x20\x20\x20\x20\x20\x60\x20\x20\x20\x60\x20\x20\x20\x3b"
3064 "\x2c\x2c\x1b\x5b\x33\x30\x6d\x24\x53\x46\x46\x46\x1b\x5b\x33\x37\x6d\x27\x22"
3065 "\x20\x20\x60\x20\x20\x20\x60\x20\x20\x20\x60\x20\x20\x20\x20\x20\x20\x20\x20"
3066 "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x0a\x20\x20\x20\x20\x20\x20\x20\x20"
3067 "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x60\x22\x1b\x5b\x33\x30\x6d\x2a\x3c\x48"
3068 "\x46\x46\x24\x53\x24\x1b\x5b\x33\x37\x6d\x53\x53\x53\x3e\x3e\x3e\x3e\x3e\x53"
3069 "\x3e\x53\x1b\x5b\x33\x30\x6d\x24\x53\x24\x46\x24\x48\x46\x23\x1b\x5b\x33\x37"
3070 "\x6d\x27\x22\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20"
3071 "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x0a\x20\x20"
3072 "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20"
3073 "\x60\x60\x22\x3c\x1b\x5b\x33\x30\x6d\x2a\x3c\x3c\x3c\x48\x46\x46\x46\x48\x46"
3074 "\x46\x46\x23\x3c\x1b\x5b\x33\x36\x6d\x3c\x1b\x5b\x33\x37\x6d\x3c\x27\x22\x22"
3075 "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20"
3076 "\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x0a\x1b"
3077 "\x5b\x30\x6d";
3078
3079 /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
This page took 0.192266 seconds and 6 git commands to generate.