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