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