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