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