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